【发布时间】:2015-04-26 15:52:47
【问题描述】:
我阅读了很多关于在存储库/UnitOfWork 模式中使用实体框架/NHibernate(或基本上任何其他现代 ORM)的内容。显然社区是分裂的。有些人会说存储库模式几乎是强制性的,有些人会说这是浪费时间...... 好吧,我想出了我的“自己的”设计,我只是想与你分享它以获得一些反馈......
过去,我的公司决定开发和使用自己的 ORM。现在完全是一场灾难。性能、稳定性(以及基本上其他一切)都很糟糕。我们想切换到另一个 ORM,并且我们希望保持从一个 ORM 切换到另一个 ORM 的能力。事实上,我们现在使用的是 Sharepoint 2010。这意味着 3.5,因此是 NHibernate 3.4 和 Entity Framework 4。我们计划尽快迁移到 SharePoint 2013,以便能够依赖 .net 4.5/EF 6.1/...所以我们将必须尽快切换到另一个 ORM。
为此,我开发了一组实现“IDatabaseContext”接口的类。
public interface IDatabaseContext : IDisposable
{
IQueryable<TEntity> AsQueryable<TEntity>()
where TEntity : EntityBase;
IList<TEntity> AsList<TEntity>()
where TEntity : EntityBase;
IList<TEntity> Find<TEntity>(Expression<Func<TEntity, bool>> predicate)
where TEntity : EntityBase;
long Count<TEntity>()
where TEntity : EntityBase;
void Add<TEntity>(TEntity entity)
where TEntity : EntityBase;
void Delete<TEntity>(TEntity entity)
where TEntity : EntityBase;
void Update<TEntity>(TEntity entity)
where TEntity : EntityBase;
}
例如,对于我决定使用 NHibernate 的原型:
public class NHibernateDbContext : IDatabaseContext
{
private ISession _session = null;
public NHibernateDbContext(ISessionFactory factory)
{
if (factory == null)
throw new ArgumentNullException("factory");
_session = factory.OpenSession();
}
public IQueryable<TEntity> AsQueryable<TEntity>()
where TEntity : EntityBase
{
return _session.Query<TEntity>();
}
public IList<TEntity> AsList<TEntity>()
where TEntity : EntityBase
{
return _session.QueryOver<TEntity>()
.List<TEntity>();
}
public IList<TEntity> Find<TEntity>(Expression<Func<TEntity, bool>> predicate)
where TEntity : EntityBase
{
...
}
public long Count<TEntity>()
where TEntity : EntityBase
{
return _session.QueryOver<TEntity>()
.RowCountInt64();
}
public void Add<TEntity>(TEntity entity)
where TEntity : EntityBase
{
if (entity == null)
throw new ArgumentNullException("entity");
UseTransaction(() => _session.Save(entity));
}
public void Delete<TEntity>(TEntity entity)
where TEntity : EntityBase
{
...
}
public void Update<TEntity>(TEntity entity)
where TEntity : EntityBase
{
...
}
private void UseTransaction(Action action)
{
using (var transaction = _session.BeginTransaction())
{
try
{
action();
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
}
}
public void Dispose()
{
if (_session != null)
_session.Dispose();
}
}
最终,我的服务层(每个实体都与一个服务相关联)依赖于这个接口,所以我不会引入对 ORM 技术的依赖。
public class CountryService<Country> : IService<Country>
where Country : EntityBase
{
private IDatabaseContext _context;
public GenericService(IDatabaseContext context)
{
if (context == null)
throw new ArgumentNullException("context");
_context = context;
}
public IList<Country> GetAll()
{
return _context.AsList<Country>();
}
public IList<Country> Find(Expression<Func<Country, bool>> predicate)
{
return _context.Find(predicate);
}
...
}
最终,要从服务层调用方法,只需要两行代码:
var service = new CountryService(new NHibernateDbContext(...)));
or
var service = new CountryService(new TestDbContext(...)));
...
我发现这种架构非常简单且使用起来非常方便。我(还)没有发现任何缺点/缺陷/错误。
那你怎么看?我错过了什么大事吗?有什么可以改进的吗?
感谢您的所有反馈...
问候, 塞巴斯蒂安
【问题讨论】:
-
session的管理不常用,什么样的应用会用到这个base?
-
SharePoint WebParts 将主要依赖这一层。此外,很少有应用程序也可能使用此层(用于不同数据源之间的同步目的)。 “管理会话”是什么意思?
标签: entity-framework nhibernate orm repository-pattern unit-of-work