gpt4 book ai didi

c# - N 层应用程序中的多个 DbContext

转载 作者:太空狗 更新时间:2023-10-29 19:57:30 26 4
gpt4 key购买 nike

我正在创建我的第一个 N 层 MVC 应用程序,但我遇到了如何使用我的数据库优先方法管理多个 DbContexts 的障碍。

我有以下图层

Presentation
Service (WCF)
Business
Data Access

我不想在我的服务层中引用 Entity Framework ,但我不知道如何创建接口(interface)或其他东西来管理两个上下文。我让它在 IDatabaseFactory 中处理单个上下文,但我似乎找不到管理两个上下文的方法。

下面是我的 UnitOfWork,它是在我的 Service ctor 中创建的,但无论我怎么看,我仍然绑定(bind)到 SiteModelContainer,而实际上我还有另一个上下文。

public class UnitOfWork : IUnitOfWork
{
private SiteModelContainer _context;

private readonly IDatabaseFactory _databaseFactory;

protected SiteModelContainer SiteContext
{
get { return _context ?? (_context = _databaseFactory.Get()); }
}

public UnitOfWork(IDatabaseFactory factory)
{
_databaseFactory = factory;
_context = _databaseFactory.Get();
}
//More code
}



public class DatabaseFactory : Disposable, IDatabaseFactory
{
private SiteModelContainer _dataContext;

public SiteModelContainer Get()
{
return _dataContext ?? (_dataContext = new SiteModelContainer());
}

protected override void DisposeCore()
{
if (_dataContext != null)
_dataContext.Dispose();
}
}

最佳答案

为您的 Factory 和 UnitOfWork 提供通用类型参数可能是一种解决方案:

public class UnitOfWork<T> : IUnitOfWork<T>
where T : DbContext, new()
{
private T _context;

private readonly IDatabaseFactory<T> _databaseFactory;

protected T Context
{
get { return _context ?? (_context = _databaseFactory.Get()); }
}

public UnitOfWork(IDatabaseFactory<T> factory)
{
_databaseFactory = factory;
_context = _databaseFactory.Get();
}
//More code
}

public class DatabaseFactory<T> : Disposable, IDatabaseFactory<T>
where T : DbContext, new()
{
private T _dataContext;

public T Get()
{
return _dataContext ?? (_dataContext = new T());
}

protected override void DisposeCore()
{
if (_dataContext != null)
_dataContext.Dispose();
}
}

IDatabaseFactoryIUnitWork 接口(interface)也必须是通用的。

然后您可以为不同的上下文创建工作单元:

var factory1 = new DatabaseFactory<SiteModelContainer>();
var unitOfWork1 = new UnitOfWork<SiteModelContainer>(factory1);

var factory2 = new DatabaseFactory<AnotherModelContainer>();
var unitOfWork2 = new UnitOfWork<AnotherModelContainer>(factory2);

编辑:

要在您的服务类中摆脱对 EF 的依赖,您可以尝试这样的事情。该服务只知道这三个接口(interface):

public interface IUnitOfWorkFactory
{
IUnitOfWork Create(string contextType);
}

public interface IUnitOfWork : IDisposable
{
IRepository<TEntity> CreateGenericRepository<TEntity>()
where TEntity : class;
void Commit();
}

public interface IRepository<T>
{
IQueryable<T> Find(Expression<Func<T, bool>> predicate);
void Attach(T entity);
void Add(T entity);
// etc.
}

以下是特定于 EF 的特殊实现:

public class UnitOfWorkFactory : IUnitOfWorkFactory
{
public IUnitOfWork Create(string contextType)
{
switch (contextType)
{
case "SiteModelContainer":
return new UnitOfWork<SiteModelContainer>();
case "AnotherModelContainer":
return new UnitOfWork<AnotherModelContainer>();
}

throw new ArgumentException("Unknown contextType...");
}
}

public class UnitOfWork<TContext> : IUnitOfWork
where TContext : DbContext, new()
{
private TContext _dbContext;

public UnitOfWork()
{
_dbContext = new TContext();
}

public IRepository<TEntity> CreateGenericRepository<TEntity>()
where TEntity : class
{
return new Repository<TEntity>(_dbContext);
}

public void Commit()
{
_dbContext.SaveChanges();
}

public void Dispose()
{
_dbContext.Dispose();
}
}

public class Repository<T> : IRepository<T>
where T : class
{
private DbContext _dbContext;
private DbSet<T> _dbSet;

public Repository(DbContext dbContext)
{
_dbContext = dbContext;
_dbSet = dbContext.Set<T>();
}

public IQueryable<T> Find(Expression<Func<T, bool>> predicate)
{
return _dbSet.Where(predicate);
}

public void Attach(T entity)
{
_dbSet.Attach(entity);
}

public void Add(T entity)
{
_dbSet.Add(entity);
}

// etc.
}

您的服务将得到一个 IUnitOfWorkFactory 注入(inject):

public class MyService
{
private IUnitOfWorkFactory _factory;

public MyService(IUnitOfWorkFactory factory)
{
_factory = factory;
}

public MyMethod()
{
using(var unitOfWork1 = _factory.Create("SiteModelContainer"))
{
var repo1 = unitOfWork1.
CreateGenericRepository<SomeEntityTypeInSiteModel>();
// Do some work
unitOfWork1.Commit();
}

using(var unitOfWork2 = _factory.Create("AnotherModelContainer"))
{
var repo2 = unitOfWork2.
CreateGenericRepository<SomeEntityTypeInAnotherModel>();
// Do some work
unitOfWork2.Commit();
}
}
}

当服务被创建时,工厂的具体实例被注入(inject):

var service = new MyService(new UnitOfWorkFactory());

请记住,艰苦的工作将在抽象存储库及其实现中进行。一旦您的服务类中不再有 EF 上下文,您就必须模仿 repo 接口(interface)中的许多方法来支持所有必要的场景来操作数据。

关于c# - N 层应用程序中的多个 DbContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6654355/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com