使用 ninject 和 nhibernate 的回购模式的多个数据库
Multiple databases using repo pattern with ninject and nhibernate
我在 nhibernate 和 ninject 中使用 repository/unit 工作模式。我有一个通用存储库,工作单元提供会话工厂。到目前为止,它一直运行良好,但现在我遇到了瓶颈。我的项目现在需要我有第二个数据库。我不能全神贯注于如何使我的 repo/unit 工作对数据库也通用。这是我的代码,从 here:
获得
存储库:
public interface IRepository<T> where T : class
{
IQueryable<T> GetAll();
T GetById(Guid id);
void Create(T entity);
void Update(T entity);
void Delete(Guid id);
}
public class Repository<T> : IRepository<T> where T : class
{
private UnitOfWork _unitOfWork;
public Repository(IUnitOfWork unitOfWork)
{
_unitOfWork = (UnitOfWork)unitOfWork;
}
protected ISession Session { get { return _unitOfWork.Session; } }
// CRUD operations...
}
工作单元:
public interface IUnitOfWork
{
void BeginTransaction();
void Commit();
}
public class UnitOfWork : IUnitOfWork
{
private static readonly ISessionFactory _sessionFactory;
private ITransaction _transaction;
public ISession Session { get; private set; }
static UnitOfWork()
{
// Initialise singleton instance of ISessionFactory, static constructors are only executed once during the
// application lifetime - the first time the UnitOfWork class is used
_sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("CONN")))
.Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.Load("MyAssembly")))
.CurrentSessionContext<WebSessionContext>()
.BuildSessionFactory();
}
public UnitOfWork()
{
Session = _sessionFactory.OpenSession();
}
public void BeginTransaction()
{
_transaction = Session.BeginTransaction();
}
public void Commit()
{
try
{
_transaction.Commit();
}
catch
{
_transaction.Rollback();
throw;
}
finally
{
Session.Close();
}
}
}
我唯一的想法是为每个数据库设置单独的存储库和工作单元 类。这对我来说真的很难看,因为它会重复很多代码。有没有办法使 repo/uow 对于数据库级别和实体类型通用?
我看到的另一个选择是 NCommon 可以为我处理这个问题。如果推荐的话,我愿意走那条路,但我还没准备好马上上床睡觉,因为该项目已经 2 年多没有更新了。
花了我一段时间,但这是我想出的,以防其他人需要这个:
修改后的回购:
public interface IRepository<TEntity, TContext> where TEntity : class where TContext : DatabaseContext
{
IQueryable<TEntity> GetAll();
TEntity GetById(Guid id);
void Create(TEntity entity);
void Update(TEntity entity);
void Delete(Guid id);
}
public class Repository<TEntity, TContext> : IRepository<TEntity, TContext> where TEntity : class where TContext : DatabaseContext
{
private UnitOfWork<TContext> _unitOfWork;
public Repository(IUnitOfWork<TContext> unitOfWork)
{
_unitOfWork = (UnitOfWork<TContext>)unitOfWork;
}
protected ISession Session { get { return _unitOfWork.Session; } }
public IQueryable<TEntity> GetAll()
{
return Session.Query<TEntity>();
}
public TEntity GetById(Guid id)
{
return Session.Get<TEntity>(id);
}
public void Create(TEntity entity)
{
Session.Save(entity);
}
public void Update(TEntity entity)
{
Session.Update(entity);
}
public void Delete(Guid id)
{
Session.Delete(Session.Load<TEntity>(id));
}
}
修改后的工作单元:
public class UnitOfWork<TContext> : IUnitOfWork<TContext> where TContext : DatabaseContext
{
private ISessionFactory _sessionFactory;
private ITransaction _transaction;
public ISession Session { get; private set; }
public UnitOfWork(TContext context)
{
if (_sessionFactory == null)
{
_sessionFactory = context.GetSessionFactory();
}
Session = _sessionFactory.OpenSession();
}
public void BeginTransaction()
{
_transaction = Session.BeginTransaction();
}
public void Commit()
{
try
{
_transaction.Commit();
}
catch
{
_transaction.Rollback();
throw;
}
finally
{
Session.Close();
}
}
}
数据库上下文:
public interface DatabaseContext
{
ISessionFactory GetSessionFactory();
}
public class QualityControlDatabaseContext : DatabaseContext
{
public ISessionFactory GetSessionFactory()
{
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("QCConnection")))
.Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.Load("QCEntities")))
.CurrentSessionContext<WebSessionContext>()
.BuildSessionFactory();
}
}
public class SAPDatabaseContext : DatabaseContext
{
public ISessionFactory GetSessionFactory()
{
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("SAPConnection")))
.Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.Load("SAPEntities")))
.CurrentSessionContext<WebSessionContext>()
.BuildSessionFactory();
}
}
我的解决方案与 Nick 相同,但我从存储库中删除以了解哪个工作单元,而是使用实体上的属性来了解它属于哪个工作单元(即哪个数据库)。更好的解决方案是检查实体映射,但我没有尝试过,所以我不知道是否可行。
存储库界面
public interface IRepository<T> where T : class
{
Task<object> SaveAsync(T entity, CancellationToken token);
Task SaveOrUpdateAsync(T entity, CancellationToken token);
Task<T> LoadAsync(object id, CancellationToken token);
Task<T> GetAsync(object id, CancellationToken token);
}
存储库实现 - 我使用 Autofac Keyed 服务。在 ctor 上,我注入了可用的工作单元。如果 class 上没有属性,我假设它是我需要的主数据库。
public class NHibernateRepository<T> : IRepository<T> where T : class
{
protected readonly ISession Session;
private readonly IUnitOfWork _unitOfWork;
public NHibernateRepository(IIndex<Core.Enum.Database, IUnitOfWork> unitOfWorks)
{
var att = typeof(T).GetCustomAttribute<DbAttribute>();
_unitOfWork = unitOfWorks[att?.Database ?? Core.Enum.Database.System];
Session = _unitOfWork.Session;
}
public Task<T> LoadAsync(object id, CancellationToken token)
{
return Session.LoadAsync<T>(id, token);
}
public Task<T> GetAsync(object id, CancellationToken token)
{
return Session.GetAsync<T>(id, token);
}
public IQueryable<T> GetQueryable()
{
return Session.Query<T>();
}
public Task<object> SaveAsync(T entity, CancellationToken token)
{
_unitOfWork.FlagCommit();
return Session.SaveAsync(entity, token);
}
public Task SaveOrUpdateAsync(T entity, CancellationToken token)
{
_unitOfWork.FlagCommit();
return Session.SaveOrUpdateAsync(entity, token);
}
}
autofac 的配置是:
builder.RegisterType<UnitOfWorkFactoryMain>().SingleInstance();
builder.RegisterType<UnitOfWorkFactorySecondary>().SingleInstance();
builder.Register(c => new UnitOfWork(c.Resolve<UnitOfWorkFactoryMain>()))
.Keyed<IUnitOfWork>(Database.System).InstancePerLifetimeScope();
builder.Register(c => new UnitOfWork(c.Resolve<UnitOfWorkFactorySecondary>()))
.Keyed<IUnitOfWork>(Database.Secondary).InstancePerLifetimeScope();
其余如尼克回答
我在 nhibernate 和 ninject 中使用 repository/unit 工作模式。我有一个通用存储库,工作单元提供会话工厂。到目前为止,它一直运行良好,但现在我遇到了瓶颈。我的项目现在需要我有第二个数据库。我不能全神贯注于如何使我的 repo/unit 工作对数据库也通用。这是我的代码,从 here:
获得存储库:
public interface IRepository<T> where T : class
{
IQueryable<T> GetAll();
T GetById(Guid id);
void Create(T entity);
void Update(T entity);
void Delete(Guid id);
}
public class Repository<T> : IRepository<T> where T : class
{
private UnitOfWork _unitOfWork;
public Repository(IUnitOfWork unitOfWork)
{
_unitOfWork = (UnitOfWork)unitOfWork;
}
protected ISession Session { get { return _unitOfWork.Session; } }
// CRUD operations...
}
工作单元:
public interface IUnitOfWork
{
void BeginTransaction();
void Commit();
}
public class UnitOfWork : IUnitOfWork
{
private static readonly ISessionFactory _sessionFactory;
private ITransaction _transaction;
public ISession Session { get; private set; }
static UnitOfWork()
{
// Initialise singleton instance of ISessionFactory, static constructors are only executed once during the
// application lifetime - the first time the UnitOfWork class is used
_sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("CONN")))
.Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.Load("MyAssembly")))
.CurrentSessionContext<WebSessionContext>()
.BuildSessionFactory();
}
public UnitOfWork()
{
Session = _sessionFactory.OpenSession();
}
public void BeginTransaction()
{
_transaction = Session.BeginTransaction();
}
public void Commit()
{
try
{
_transaction.Commit();
}
catch
{
_transaction.Rollback();
throw;
}
finally
{
Session.Close();
}
}
}
我唯一的想法是为每个数据库设置单独的存储库和工作单元 类。这对我来说真的很难看,因为它会重复很多代码。有没有办法使 repo/uow 对于数据库级别和实体类型通用?
我看到的另一个选择是 NCommon 可以为我处理这个问题。如果推荐的话,我愿意走那条路,但我还没准备好马上上床睡觉,因为该项目已经 2 年多没有更新了。
花了我一段时间,但这是我想出的,以防其他人需要这个:
修改后的回购:
public interface IRepository<TEntity, TContext> where TEntity : class where TContext : DatabaseContext
{
IQueryable<TEntity> GetAll();
TEntity GetById(Guid id);
void Create(TEntity entity);
void Update(TEntity entity);
void Delete(Guid id);
}
public class Repository<TEntity, TContext> : IRepository<TEntity, TContext> where TEntity : class where TContext : DatabaseContext
{
private UnitOfWork<TContext> _unitOfWork;
public Repository(IUnitOfWork<TContext> unitOfWork)
{
_unitOfWork = (UnitOfWork<TContext>)unitOfWork;
}
protected ISession Session { get { return _unitOfWork.Session; } }
public IQueryable<TEntity> GetAll()
{
return Session.Query<TEntity>();
}
public TEntity GetById(Guid id)
{
return Session.Get<TEntity>(id);
}
public void Create(TEntity entity)
{
Session.Save(entity);
}
public void Update(TEntity entity)
{
Session.Update(entity);
}
public void Delete(Guid id)
{
Session.Delete(Session.Load<TEntity>(id));
}
}
修改后的工作单元:
public class UnitOfWork<TContext> : IUnitOfWork<TContext> where TContext : DatabaseContext
{
private ISessionFactory _sessionFactory;
private ITransaction _transaction;
public ISession Session { get; private set; }
public UnitOfWork(TContext context)
{
if (_sessionFactory == null)
{
_sessionFactory = context.GetSessionFactory();
}
Session = _sessionFactory.OpenSession();
}
public void BeginTransaction()
{
_transaction = Session.BeginTransaction();
}
public void Commit()
{
try
{
_transaction.Commit();
}
catch
{
_transaction.Rollback();
throw;
}
finally
{
Session.Close();
}
}
}
数据库上下文:
public interface DatabaseContext
{
ISessionFactory GetSessionFactory();
}
public class QualityControlDatabaseContext : DatabaseContext
{
public ISessionFactory GetSessionFactory()
{
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("QCConnection")))
.Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.Load("QCEntities")))
.CurrentSessionContext<WebSessionContext>()
.BuildSessionFactory();
}
}
public class SAPDatabaseContext : DatabaseContext
{
public ISessionFactory GetSessionFactory()
{
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("SAPConnection")))
.Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.Load("SAPEntities")))
.CurrentSessionContext<WebSessionContext>()
.BuildSessionFactory();
}
}
我的解决方案与 Nick 相同,但我从存储库中删除以了解哪个工作单元,而是使用实体上的属性来了解它属于哪个工作单元(即哪个数据库)。更好的解决方案是检查实体映射,但我没有尝试过,所以我不知道是否可行。
存储库界面
public interface IRepository<T> where T : class
{
Task<object> SaveAsync(T entity, CancellationToken token);
Task SaveOrUpdateAsync(T entity, CancellationToken token);
Task<T> LoadAsync(object id, CancellationToken token);
Task<T> GetAsync(object id, CancellationToken token);
}
存储库实现 - 我使用 Autofac Keyed 服务。在 ctor 上,我注入了可用的工作单元。如果 class 上没有属性,我假设它是我需要的主数据库。
public class NHibernateRepository<T> : IRepository<T> where T : class
{
protected readonly ISession Session;
private readonly IUnitOfWork _unitOfWork;
public NHibernateRepository(IIndex<Core.Enum.Database, IUnitOfWork> unitOfWorks)
{
var att = typeof(T).GetCustomAttribute<DbAttribute>();
_unitOfWork = unitOfWorks[att?.Database ?? Core.Enum.Database.System];
Session = _unitOfWork.Session;
}
public Task<T> LoadAsync(object id, CancellationToken token)
{
return Session.LoadAsync<T>(id, token);
}
public Task<T> GetAsync(object id, CancellationToken token)
{
return Session.GetAsync<T>(id, token);
}
public IQueryable<T> GetQueryable()
{
return Session.Query<T>();
}
public Task<object> SaveAsync(T entity, CancellationToken token)
{
_unitOfWork.FlagCommit();
return Session.SaveAsync(entity, token);
}
public Task SaveOrUpdateAsync(T entity, CancellationToken token)
{
_unitOfWork.FlagCommit();
return Session.SaveOrUpdateAsync(entity, token);
}
}
autofac 的配置是:
builder.RegisterType<UnitOfWorkFactoryMain>().SingleInstance();
builder.RegisterType<UnitOfWorkFactorySecondary>().SingleInstance();
builder.Register(c => new UnitOfWork(c.Resolve<UnitOfWorkFactoryMain>()))
.Keyed<IUnitOfWork>(Database.System).InstancePerLifetimeScope();
builder.Register(c => new UnitOfWork(c.Resolve<UnitOfWorkFactorySecondary>()))
.Keyed<IUnitOfWork>(Database.Secondary).InstancePerLifetimeScope();
其余如尼克回答