如何在Service和Repository之间注入相同的dbcontext实例?

时间:2015-09-01 04:02:20

标签: c# entity-framework dependency-injection repository-pattern

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

的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然后服务 。这意味着我将实体添加到单独的上下文中并使用不同的上下文进行保存。

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

3 个答案:

答案 0 :(得分:1)

工作单元存储库等模式有很多方法可以实现。 F.E.您可以实现返回具有方法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

答案 1 :(得分:0)

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

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
}

答案 2 :(得分:0)

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

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

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

确保使用构造函数注入后,您现在可以在composition root中编写整个对象图。执行此操作时,请确保对UnitOfWork和服务使用相同的DatabaseContext实例。 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
        ....
    }