c# - tutorial - mvc entity framework example




實體框架5更新記錄 (5)

在ASP.NET MVC3環境中,我一直在探索在Entity Framework 5中編輯/更新記錄的不同方法,但到目前為止,他們都沒有勾選我需要的所有框。 我會解釋為什麼。

我已經找到了三種方法,我會提及利弊:

方法1 - 加載原始記錄,更新每個屬性

var original = db.Users.Find(updatedUser.UserId);

if (original != null)
{
    original.BusinessEntityId = updatedUser.BusinessEntityId;
    original.Email = updatedUser.Email;
    original.EmployeeId = updatedUser.EmployeeId;
    original.Forename = updatedUser.Forename;
    original.Surname = updatedUser.Surname;
    original.Telephone = updatedUser.Telephone;
    original.Title = updatedUser.Title;
    original.Fax = updatedUser.Fax;
    original.ASPNetUserId = updatedUser.ASPNetUserId;
    db.SaveChanges();
}    

優點

  • 可以指定哪些屬性更改
  • 視圖不需要包含每個屬性

缺點

  • 2 x查詢數據庫以加載原始數據然後進行更新

方法2 - 加載原始記錄,設置更改的值

var original = db.Users.Find(updatedUser.UserId);

if (original != null)
{
    db.Entry(original).CurrentValues.SetValues(updatedUser);
    db.SaveChanges();
}

優點

  • 只有修改過的屬性才會發送到數據庫

缺點

  • 視圖需要包含每個屬性
  • 2 x查詢數據庫以加載原始數據然後進行更新

方法3 - 附加更新的記錄並將狀態設置為EntityState.Modified

db.Users.Attach(updatedUser);
db.Entry(updatedUser).State = EntityState.Modified;
db.SaveChanges();

優點

  • 1 x查詢數據庫進行更新

缺點

  • 無法指定哪些屬性更改
  • 視圖必須包含每個屬性

我對你們的問題; 有沒有一種干淨的方式可以實現這一套目標?

  • 可以指定哪些屬性更改
  • 視圖不需要包含每個屬性(如密碼!)
  • 1 x查詢數據庫進行更新

我知道這是一個很小的事情要指出,但我可能會錯過一個簡單的解決方案。 如果不是方法一將佔上風;-)


只是添加到選項列表。 您也可以從數據庫中獲取對象,然後使用Auto Mapper之類的自動映射工具更新要更改的記錄部分。


您正在尋找:

db.Users.Attach(updatedUser);
var entry = db.Entry(updatedUser);
entry.Property(e => e.Email).IsModified = true;
// other changed properties
db.SaveChanges();

我非常喜歡接受的答案。 我相信還有另一種方法來處理這個問題。 假設您有一個非常短的屬性列表,您不希望將其添加到視圖中,因此更新實體時,這些屬性將被忽略。 假設這兩個字段是密碼和SSN。

db.Users.Attach(updatedUser);

var entry = db.Entry(updatedUser);
entry.State = EntityState.Modified;

entry.Property(e => e.Password).IsModified = false;
entry.Property(e => e.SSN).IsModified = false;   

db.SaveChanges();   

這個例子允許你在你的用戶表和你的視圖中添加一個新的字段後,基本上保持你的業務邏輯不變。


根據您的使用情況,所有上述解決方案都適用。 然而,我通常這樣做:

對於服務器端代碼(例如批處理),我通常加載實體並使用動態代理。 通常在批處理過程中,您需要在服務運行時加載數據。 我嘗試批量加載數據,而不是使用find方法來節省一些時間。 根據我使用樂觀或悲觀並發控制的過程(我總是使用樂觀的,除了平行執行的場景,我需要用普通的sql語句來鎖定一些記錄,儘管這很少見)。 根據代碼和情況,影響可以降至幾乎為零。

對於客戶端方案,您有幾個選項

  1. 使用視圖模型。 模型應該有一個屬性UpdateStatus(未修改插入更新刪除)。 客戶有責任根據用戶操作(insert-update-delete)為此列設置正確的值。 服務器可以向數據庫查詢原始值,或者客戶端應該將原始值與已更改的行一起發送到服務器。 服務器應附加原始值並為每行使用UpdateStatus列來決定如何處理新值。 在這種情況下,我總是使用樂觀並發。 這只會執行插入 - 更新 - 刪除語句而不是任何選擇,但它可能需要一些巧妙的代碼來走圖和更新實體(取決於您的場景 - 應用程序)。 映射器可以幫助但不處理CRUD邏輯

  2. 使用像breeze.js這樣的庫來隱藏大部分的複雜性(如1中所述),並嘗試將其適用於您的用例。

希望能幫助到你


public interface IRepository
{
    void Update<T>(T obj, params Expression<Func<T, object>>[] propertiesToUpdate) where T : class;
}

public class Repository : DbContext, IRepository
{
    public void Update<T>(T obj, params Expression<Func<T, object>>[] propertiesToUpdate) where T : class
    {
        Set<T>().Attach(obj);
        propertiesToUpdate.ToList().ForEach(p => Entry(obj).Property(p).IsModified = true);
        SaveChanges();
    }
}




entity-framework-5