2

我目前正在寻找一种设计模式,或者说是一种最佳实践,用于实现使用实体框架 5 和代码优先方法Repository<Entity>.Update()的应用程序的方法。ASP.NET MVC 4

问题: 我遇到的问题是,当从数据库中查询实体并显示在视图上时,它可能没有填充所有属性。因此,当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。
  • 实施视图模型并使用域模型来回转换数据。

    • 这是迄今为止我能想到的最好的方法。绑定到视图模型的所有属性将始终被填充,在更新 POST 上,将所有视图模型值复制到域模型。

非常感谢您对此的想法。

4

1 回答 1

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
        ...
    }

这是我能想到的最好的解决方案。你想要最少的代码和良好的性能。这就像找到一份简单而高薪的工作一样困难。

于 2013-01-12T19:37:45.353 回答