仓储模式 EF Core Update 方法

10

我对在使用Entity Framework Core的MVC Web应用程序中使用存储库模式和工作单元模式有一个问题。

我目前正在控制器中实现更新功能。 现在,在此时我不确定更新实体的最佳方法是什么。 我看过一些视频,他们说在这样的存储库中不应该存在Update方法:

public T Update(T entity)
{
  DbSet.Attach(entity);
  var entry = Context.Entry(entity);
  entry.State = System.Data.EntityState.Modified;
}

那就意味着我需要在控制器中这样做:
public IActionResult Edit(int id, [Bind("NeighbourhoodGroup,Neighbourhood,NeighbourhoodId")] Neighbourhoods neighbourhoods)
{
  var neighbourhoodsFound = unitOfWork.Neighbourhoods.Get(id);
  neighbourhoodsFound.Neighbourhood = neighbourhoods.Neighbourhood;
  neighbourhoodsFound.NeighbourhoodGroup = neighbourhoods.NeighbourhoodGroup;
}

然而,这意味着我必须在所有控制器中执行此操作,即使该对象具有许多属性?

我希望有人能给我一些关于最佳方法的建议。


1
你不需要一个Update方法,也不需要一个仓库。你正在破坏EF Core并试图重新实现已经实现的内容。顺便说一句,那个“update”方法并没有更新任何东西,它只是将一个分离的实体附加到修改状态。你确实需要附加一个新实体。 - Panagiotis Kanavos
1
检查[使用Entity Framework Core时不需要存储库和工作单元](https://gunnarpeipman.com/ef-core-repository-unit-of-work/)。Gunnar Peipman在一篇文章中收集了所有这些通用存储库的问题。 - Panagiotis Kanavos
2个回答

3
在您的代码库中,您可以轻松实现更新的功能,如下所示:

public void Update(T entity)
    {
        DbSet.Attach(entity);
        ApplicationContext.Entry(entity).State = EntityState.Modified;
    }

在控制器或您喜欢的其他位置中,您可以通过id获取实体,修改要在实体上修改的所有属性,从存储库调用Update方法,该方法将其状态设置为modified,最后在EF上下文上调用Save或SaveAsync方法。您的EF上下文应在UnitOfWork中公开。

有关更详细的说明,请参见此帖子,它将非常有帮助。EF Repository模式


5
EF上下文是工作单元,DbSet是“通用”存储库。那篇文章中展示的通用存储库是反模式。请查看Gunnar Peipman的网站,了解不需要使用Entity Framework Core中的存储库和工作单元。Gunnar Peipman在一篇文章中总结了所有通用存储库的问题,因此我们不必重复它们。 - Panagiotis Kanavos

0
  1. 我认为在存储库中拥有 Update 方法并没有问题。这是可以接受的。更复杂的是根据条件从存储库中读取数据。你可以在Microsoft中查看一个示例。
  2. 控制器不是描述业务用例的好地方:做一些业务逻辑,然后保存到存储库等。考虑使用MediatR来描述特定的业务用例,而不是将其放入控制器中。

此外,阅读关于清洁架构的文章也很有用。


3
这绝对不行。像那样拥有一个“通用存储库”本身就是一个非常糟糕的想法。你链接的文章并没有展示一个通用存储库,它展示了一个非常具体的存储库,只添加EF本身没有提供的功能。 - Panagiotis Kanavos
1
请查看使用Entity Framework Core时无需使用存储库和工作单元,该文章列出了由通用存储库引起的问题列表。使用这些通用存储库会导致你失去工作单元、不需要成本的事务、批量更新,并在更高级别的抽象层之上强制执行低级别的抽象。 - Panagiotis Kanavos
阅读文章。你根本不需要那个事务。这就是 SaveChanges 的作用,也是为什么 DbContext 是 UoW。正是因为通用存储库,现在你需要一个额外的长期事务来处理整个请求。更糟糕的是,每个请求一个事务从来没有意味着每个请求一个数据库事务。这是一个术语,早在10多年前就被引入到J2EE应用程序中,当ORM处于萌芽状态时,它指的是J2EE容器事务。现代ORM不需要它们。 - Panagiotis Kanavos
1
通用存储库试图成为万能解药。而你所提到的是一个例子,说明为什么你不需要通用存储库,以及如果你真的需要它们,如何轻松使用事务。但通常情况下你并不需要,因为SaveChanges已经使用了事务。 - Panagiotis Kanavos
1
关于仓库的生命周期,它是在using块中定义的。在 DI 场景中,只有在存在适当的作用域时,我们才能将生命周期管理交给其他人。例如,ASP.NET Core 通过中间件处理所有作用域和瞬态服务的释放。但是,如果没有调用SaveChanges,就不会有需要回滚的更改。 - Panagiotis Kanavos
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接