【问题标题】:GenericRepository pattern Update methodGenericRepository 模式更新方法
【发布时间】:2014-10-29 16:46:49
【问题描述】:

我正在尝试使用 unitofwork 和存储库模式,并且如果我要替换表行中的所有元素(id、颜色、年份),我有以下“更新”方法可以正常工作。

public virtual void Update(TEntity entityToUpdate)
{
    dbSet.Attach(entityToUpdate);
    (entityToUpdate).State = EntityState.Modified;
}

但我只想更新我传递的特定列(id 和颜色)。它将覆盖其他元素(年份)。

例如,我的 Cars 表中有一条数据库记录:

Id = 1,
color = "red"
year = 2010

如果我像这样更新它......

var location = new Car
{
    Id = 1,
    color = "blue"
};


unitOfWork.CarRepository.Update(car);

现在的记录是:

Id = 1,
color = "blue"
year = null 

我如何重写我的通用存储库方法来更改我提供的内容? (即保持年份值)

【问题讨论】:

    标签: c# asp.net-mvc repository-pattern unit-of-work


    【解决方案1】:

    您将无法使用通用存储库模式合理地做到这一点。你真的没有必要使用这种模式。 EntityFramework 已经是一个通用存储库,为什么需要将它包装在另一个通用存储库中?这种类型的抽象增加了负值。

    您确实希望从您的控制器封装您的数据库使用(在 MVC 控制器中不应该有 DbContext),但是您不需要任何特殊模式来执行此操作。只需将 DbContext 注入到一个可以工作的类中。

    如果您传递 UOW,那么大部分工作单元模式也是反模式。这会在您的应用程序中产生一些非常疯狂的耦合问题,完全不相关的代码能够影响截然不同的代码段。

    删除通用存储库并直接在您的服务/DAL/资源类(无论您想如何称呼它)中使用 EF 将允许您使用 EF 的全部功能。这将允许非常简单地进行部分更新。

    要对通用存储库进行部分更新,您将需要一些重型动态代码来处理映射。老实说,我理论上可以写这个,但我知道不要写这个。您使映射变得越来越抽象,它变得越脆弱,几乎不可能预测未来如何处理映射。这就是为什么有像 AutoMapper 这样的完整库来处理如何完成映射的无限组合。 AutoMapper 也有点用词不当,虽然它可以在大多数情况下进行基本的自动映射,但 AutoMapper 的用例仍然是所有静态映射而不是动态映射。您需要创建动态映射,也就是水晶球映射。

    【讨论】:

    • 直接使用实体时如何测试您的服务/DAL/资源?您是否不必模拟您需要测试的服务/DAL/资源方法中使用的每个实体方法才能做到这一点?
    • @afarazit 我从不模拟数据库,这毫无意义。我嘲笑抽象,“DAL”。有时这可能意味着我的模拟 DAL 使用字典来模拟 [快速] 集成测试的持久性。
    • @ChrisMarisic - 你能指出一些描述模拟 DAL 而不是数据库的实现的文章。因为我也一直在模拟 db 来测试我的服务。
    • @Nanu 我不知道。模拟数据库是没有意义的,那时你什么都没有测试。您不知道您的代码可以工作,它是否适用于模拟数据库并不重要。你只是浪费了大量的精力。
    【解决方案2】:

    您编写的更新方法假定您已从已设置属性的现有实体对象开始。存储库假定您的业务逻辑是这样工作的:

    var car = repo.GetCar(id);
    
    car.prop1 = "new value";
    car.prop2 = "another new value";
    
    repo.update(car);
    

    这将保留您之前设置的所有值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多