使用哪种方法取决于存储库的责任。
存储库有责任运行完整事务吗?即进行更改,然后通过调用SaveChanges将更改保存到数据库中?还是仅是较大事务的一部分,因此仅进行更改而不保存更改?
情况1)存储库将运行完整的事务(它将进行更改并保存):
在这种情况下,第二种方法更好(第二种代码示例的方法)。
我将仅通过引入如下工厂来稍微修改此方法:
public interface IFactory<T>
{
T Create();
}
public class Repository : IRepository
{
private IFactory<MyContext> m_Factory;
public Repository(IFactory<MyContext> factory)
{
m_Factory = factory;
}
public void AddCustomer(Customer customer)
{
using (var context = m_Factory.Create())
{
context.Customers.Add(customer);
context.SaveChanges();
}
}
}
我正在做此微小更改以启用依赖关系注入。这使我们能够在以后更改创建上下文的方式。
我不希望存储库负责创建自己的上下文。实施工厂IFactory<MyContext>
将负责创建上下文。
请注意,存储库是如何管理上下文的生存期的,它创建了上下文,进行了一些更改,保存了更改,然后处置了上下文。在这种情况下,存储库的生存期比上下文长。
案例2:存储库是更大事务的一部分(它将进行一些更改,其他存储库将进行其他更改,然后其他人将通过调用来提交事务SaveChanges
):
在这种情况下,第一种方法(您先在问题中描述)会更好。
想象一下,继续了解存储库如何成为更大事务的一部分:
using(MyContext context = new MyContext ())
{
repository1 = new Repository1(context);
repository1.DoSomething();
repository2 = new Repository2(context);
repository2.DoSomething();
context.SaveChanges();
}
请注意,每个事务都使用存储库的新实例。这意味着存储库的生存期非常短。
请注意,我正在代码中新建存储库(这违反了依赖注入)。我只是以这个为例。在实际代码中,我们可以使用工厂来解决此问题。
现在,我们可以对该方法进行的一项增强功能是将上下文隐藏在接口后面,以使存储库不再具有访问权限SaveChanges
(请参阅“接口隔离原理”)。
您可以有以下内容:
public interface IDatabaseContext
{
IDbSet<Customer> Customers { get; }
}
public class MyContext : DbContext, IDatabaseContext
{
public IDbSet<Customer> Customers { get; set; }
}
public class Repository : IRepository
{
private IDatabaseContext m_Context;
public Repository(IDatabaseContext context)
{
m_Context = context;
}
public void AddCustomer(Customer customer)
{
m_Context.Customers.Add(customer);
}
}
如果需要,可以将所需的其他方法添加到接口。
另请注意,此接口不继承自IDisposable
。这意味着Repository
该类不负责管理上下文的生存期。在这种情况下,上下文的生存期比存储库更长。其他人将管理上下文的生存期。
关于第一篇文章的注释:
第一篇文章建议您不应使用在问题中描述的第一种方法(将上下文注入存储库中)。
关于如何使用存储库,本文尚不清楚。它是否用作单笔交易的一部分?还是跨多个交易?
我猜(我不确定),在本文所描述的方法中(否定性地),存储库用作长期运行的服务,将涉及许多事务。在这种情况下,我同意该文章。
但是我在这里提出的建议是不同的,我建议仅在每次需要事务时都创建存储库的新实例的情况下使用此方法。
关于第二篇文章的注释:
我认为第二篇文章所讨论的内容与您应该使用哪种方法无关。
第二篇文章讨论了在任何情况下(与存储库的设计无关)是否有必要处置上下文。
请注意,在两种设计方法中,我们正在处理上下文。唯一的区别是谁负责这种处置。
文章说,DbContext
似乎可以清理资源而无需显式处理上下文。