如何在服务和存储库之间注入相同的 dbcontext 实例?

How to inject same dbcontext instance between Service and Repository?

嗨,我正在做一个项目,目前我正在使用 entity framework

构建数据层

Dbcontext

public interface IDatabaseContext : IDisposable 
    {        
        IDbSet<TestEntity> TestEntitys { get; }
        int SaveChanges();
    }



public class DatabaseContext : DbContext, IDatabaseContext
    {
        static DatabaseContext()
        {
            System.Data.Entity.Database.SetInitializer<DatabaseContext>(null);
        }

        public DatabaseContext(string connectionString) :
            base(connectionString)
        {
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {          

            modelBuilder.Configurations.Add(new TestEntityConfiguration());
            base.OnModelCreating(modelBuilder);
        }                  

        public IDbSet<TestEntity> TestEntitys
        {
            get;
            set;
        }

        public override int SaveChanges()
        {           

            return base.SaveChanges();
        }

    }

工作单元:

public interface IUnitOfWork : IDisposable
{   
    int Commit();
    IDatabaseContext Context { get; }
}

  public sealed class UnitOfWork : IUnitOfWork, IDisposable
{

    private  IDatabaseContext _dbContext;
    private bool disposed = false;

    public UnitOfWork(IDatabaseContext mydbContext)
    {    
         //var builder=DataBaseConnectionStringBuilder();
         //var factory = new DataBaseConnectionFactory(builder);      

        _dbContext = mydbContext;

    }

    public int Commit()
    {

        return _dbContext.SaveChanges();
    }

    public IDatabaseContext Context
    {
        get { return _dbContext; }
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }


    private void Dispose(bool disposing)
    {     
        if (!disposed)
        {
            if (disposing)
            {
                if (_dbContext != null)
                {
                    _dbContext.Dispose();
                    _dbContext = null;
                }
            }
        }
        disposed = true;
    }
}

服务:

public class Baseservice()
{
    protacted IUnitOfWork unitofwork;
    public BaseService(IUnitOfWork uow)
    {
        unitofwork= uow;
    }
}
public class TestEntityservice() : BaseService
{
    private ITestEntityReopsitory _testEntityReopsitory;
    public TestEntityservice(IUnitOfWork uow,ITestEntityReopsitory testEntityReopsitory):base(uow)
    {
        _testEntityReopsitory=testEntityReopsitory;
    }
    public int AddNewData(somedto dto){

        var result=_testEntityReopsitory.AddTEst(dto);
        return  unitofwork.Commit();
    }
}

存储库:

 public BaseRepository(IDatabaseContext context)
        {
            _dbContext = context;            
        }
public class TestEntityReopsitory() : BaseRepository, ITestEntityReopsitory
{

    public TestEntityReopsitory(IDatabaseContext context) :base(context) {        
    }
    public int AddTEst(somedto dto){
        var entity = new TestEntity()
        {
            a= dto.a,
            b= dto.b
        }
        context.Add(entity);
    }
}   

我担心的是,因为我在存储库中注入我的数据库上下文 (DatabaseContext),所以当存储库解析时,它将有一个 单独的实例 of dbcontext in存储库然后服务。所以这意味着我要将实体添加到单独的上下文并使用不同的上下文进行保存。

我如何确保我在存储库和服务中使用相同的实例并且仍然保持相同的实现。

实现此目的的一种方法是跨存储库实例共享工作单元,这将允许您创建如下代码

using (IUnitOfWork unitOfWork = _UnitOfWorkFactory.CreateInstance()) {
   var repository = _RepositoryFactory.CreateRepository<YourType>(unitOfWork);
   var repositoryTwo = _RepositoryFactory.CreateRepository<YourOtherType>(unitOfWork);
    unitOfWork.Commit();
}

存储库工厂

BaseRepository IRepositoryFactory.CreateRepository<T>(IUnitOfWork unitOfWork) {
       //Create Instance Here
}

在您的 UnitOfWork class 中,不是创建工厂然后使用它来创建 IDatabaseContext 对象,而是使用构造函数注入来注入 DatabaseContext。像这样:

public UnitOfWork(IDatabaseContext db_context)
{    
    _dbContext = db_context;
}

也为 Baseservice(以及 TestEntityservice)做同样的事情,他们应该在他们的构造函数中注入 IUnitOfWork,他们不应该自己创建 UnitOfWork。这就是依赖注入的意义所在。

在确保使用构造函数注入后,您现在可以在 composition root. When you do that, make sure that you use the same DatabaseContext instance for both your UnitOfWork and your service. Pure DI 中组合整个对象图,这是一种非常好的组合方式。

以下是使用 Pure DI 执行此操作的方法:

    var connection_string = "some connection string";

    using (IDatabaseContext context = new DatabaseContext(connection_string))
    {
        IUnitOfWork unit_of_work = new UnitOfWork(context);

        ITestEntityReopsitory reopsitory = new TestEntityReopsitory(context);

        ITestEntityservice service = new TestEntityservice(unit_of_work, reopsitory);

        //Consume service here
        ....
    }

Unit of workrepository 等模式有多种实现方式。 F.e。您可以实现 returns 活动记录 具有方法 UpdateDelete 的只读存储库。或者您可以实现 returns 普通旧对象 的存储库,因此具有方法 UpdateDelete。最后,您可以实现 returns 普通旧对象 的只读存储库,因此方法 UpdateDelete 应该在 [=30= 中声明]工作单元.

如何组织存储库和工作单元的交互?这可以通过组合模式 registryunit of work:

来完成
public interface IUnitOfWork
{
    IUserRepository UserRepository { get; }

    IDataRepository DataRepository { get; }

    void Commit();
}

或者您可以使用工作单元作为 服务定位器:

public interface IUnitOfWork
{
    TRepository GetRepository<TRepository>() where TRepository: IRepository;

    void Commit();
}

或者您可以明确指定工作单元的读写存储库:

public interface IUnitOfWork
{
    void Join(IRepository repository);

    void Commit();
}

在最后一种情况下,您可以使用带有工作单元的存储库,也可以不使用它们。在所有这些情况下,您可以在存储库和工作单元之间共享相同的 DbContext