C# 通用存储模式更新方法

C# 通用存储模式更新方法,c#,asp.net-mvc,repository-pattern,unit-of-work,C#,Asp.net Mvc,Repository Pattern,Unit Of Work,我正在尝试使用unitofwork和repository模式,如果我替换表行中的所有元素(id、颜色、年份),我有以下“更新”方法可以很好地工作 但是我只想更新我正在传递的特定列(id和颜色)。它将覆盖其他元素(年) 例如,我的Cars表中有一条数据库记录: Id = 1, color = "red" year = 2010 如果我像这样更新它 var location = new Car { Id = 1, color = "blue" }; unitOfWork.Car

我正在尝试使用unitofwork和repository模式,如果我替换表行中的所有元素(id、颜色、年份),我有以下“更新”方法可以很好地工作

但是我只想更新我正在传递的特定列(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 

我如何重写我的泛型存储库方法来改变我提供给它的内容?(即保留年份值)

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

您确实希望从控制器中封装数据库使用情况(MVC控制器中不应该有DbContext),但是不需要任何特殊的模式。只需将DbContext注入一个有效的类

此外,如果您传递UOW,那么工作单元模式在大多数情况下是反模式。这在您的应用程序中造成了一些非常疯狂的耦合问题,完全不相关的代码能够影响截然不同的代码段

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


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

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

var car = repo.GetCar(id);

car.prop1 = "new value";
car.prop2 = "another new value";

repo.update(car);

这将保留您以前设置的任何值。

当直接使用实体时,您将如何测试您的服务/DAL/资源?要做到这一点,您是否需要模拟需要测试的服务/DAL/resource方法中使用的每个实体方法?@afarazit我从不模拟数据库,这是毫无意义的。我嘲笑抽象的“DAL”。有时这可能意味着我的模拟DAL使用字典来模拟[快速]集成测试的持久性。@chrismaric-你能指出一些描述模拟DAL而不是数据库实现的文章吗。因为我也一直在模仿db来测试我的服务。@Nanu我没有。模拟数据库是没有意义的,在这一点上你什么都没有测试。您不知道您的代码是否可以工作,它是否可以针对模拟数据库工作并不重要。你只是浪费了很多精力。
var car = repo.GetCar(id);

car.prop1 = "new value";
car.prop2 = "another new value";

repo.update(car);