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

本文关键字:注入 实例 dbcontext 之间 服务 存储 | 更新日期: 2023-09-27 18:10:33

嗨,我正在做一个项目,目前我正在用实体框架构建数据层

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),所以当存储库将解决它时,它将在存储库中有一个单独的实例 dbcontext,然后服务。因此,这意味着我将一个实体添加到一个单独的上下文,并使用不同的上下文保存。

我怎样才能确保我在存储库和服务中使用相同的实例,并且仍然保持相同的实现。

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

工作单元存储库这样的模式有很多实现的方法。例如,您可以实现只读存储库,它返回具有方法UpdateDelete活动记录。或者您可以实现返回普通旧对象的存储库,因此具有UpdateDelete方法。最后,您可以实现返回普通旧对象的只读存储库,因此方法UpdateDelete应该在工作单元中声明。

如何组织存储库和工作单元之间的交互?这可以通过组合模式注册表工作单元:

来实现。
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

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

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

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

确保使用构造函数注入后,现在可以在组合根中组合整个对象图。当你这样做的时候,确保你为你的UnitOfWork和你的服务使用了相同的DatabaseContext实例。纯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
        ....
    }

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

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
}