2013-01-12 90 views
2

我目前正在尋找一種設計模式,而不是實施Repository<Entity>.Update()方法的ASP.NET MVC 4應用程序,該應用程序使用實體框架5和代碼優先方法。ASP.NET MVC實體框架 - 實體更新 - 用空值覆蓋數據庫值

問題: 我遇到的問題是,當從數據庫查詢實體並顯示在視圖上時,它可能沒有填充所有的屬性。因此,當調用repository.Update(entity)方法時,傳遞給Update()方法的實體可能具有包含空值的未綁定屬性。但是它們可能在數據庫中有一些值。在下面的代碼中以Customer.Misc爲例。

所以問題來了。根據這種方法,在第一個Update()方法調用之後,數據庫中沒有綁定在視圖上的所有屬性都設置爲Null。

class Customer 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Misc { get; set; } 
} 

[HttpGet] 
public ActionResult Update(int id) 
{ 
    Repository<Customer> repo = new Repository<Customer>(); 
    return View(repo.GetById(id)); // View only binds Customer.Name 
} 

[HttpPost] 
public ActionResult Update(Customer customer) 
{ 
    Repository<Customer> repo = new Repository<Customer>(); 
    repo.Update(customer); // Customer.Misc is null 
    ... 
} 

public void Update(TEntity entity) 
{ 
    var entry = DbContext.Entry<TEntity>(entity); 
    if (entry.State == EntityState.Detached) 
    { 
     ObjectContext.ApplyCurrentValues(EntitySetName, entity); 
    } 
    DbContext.SaveChanges(); 
} 

解決方案我能想到:

  • 綁定視圖中的所有實體屬性:

    • 我認爲這是不可行的,並在同一時間,它可能會導致性能問題因爲所有屬性都被填充。
  • 實現自定義方法來複制屬性值以避免複製空值。

    • EntityHelper.CopyNotNullValues(source, target)並忽略源實體中的空值。如果我們這樣做,如果需要,我們可能無法將任何值設置爲null。
  • 實現視圖使用域模型來回模型和變換數據。

    • 這是迄今爲止我能想到的最好方法。綁定到視圖模型的所有屬性將始終填充,在Update POST上將所有視圖模型值複製到域模型。

真的很感謝您對此的看法。

回答

0

在Entity Framework中,使用ChangeObjectState或ApplyCurrentValues會導致數據丟失。在這種情況下解決此問題的唯一方法是附加輸入實體並標記要更新的屬性。看下面的例子:

public void Update(TEntity entity, string[] updatedProperties) 
    { 
     DbContext.Entities.Attach(entity); 
     var entry = DbContext.Entry<TEntity>(entity); 
     for (int i = 0; i < updatedProperties.Length; i++) 
     { 
      entry.SetModifiedProperty(updatedProperties[i]); 
     } 
     DbContext.SaveChanges(); 
    } 

    [HttpPost] 
    public ActionResult Update(Customer customer) 
    { 
     Repository<Customer> repo = new Repository<Customer>(); 
     repo.Update(customer, new string[]{ "Name" }); // Only update name 
     ... 
    } 

這是我能想到的最好的解決方案。你想要最少的代碼和良好的性能。這與尋找一份簡單而又高薪的工作一樣困難。