gpt4 book ai didi

linq - 如何实现与 EF 和 NHibernate 一起使用的工作单元

转载 作者:行者123 更新时间:2023-12-03 20:21:28 25 4
gpt4 key购买 nike

我正在研究一个在 Entity Framework 4.1 和 NHibernate 中都可以工作的工作单元实现。在下面找到我的实现细节的骨架

IUnitOfWork 定义

public interface IUnitOfWork
{
IRepository<LogInfo> LogInfos { get; }
IRepository<AppInfo> AppInfos { get; }
void Commit();
void Rollback();
}

IRepository 定义
public interface IRepository<T> where T : class, IEntity
{
IQueryable<T> FindAll();
IQueryable<T> FindWhere(Expression<Func<T, bool>> predicate);
T FindById(int id);
void Add(T newEntity);
void Remove(T entity);
}

NHibernate中UoW的实现
public class NHibernateUnitOfWork : IUnitOfWork, IDisposable
{
public ISession Session { get; private set; }

public NHibernateUnitOfWork(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
Session = _sessionFactory.OpenSession();
_transaction = Session.BeginTransaction();
}

public IRepository<LogInfo> LogInfos
{
get
{
if (_logInfo == null)
{
_logInfo = new NHibernateRepository<LogInfo>(Session);
}

return _logInfo;
}
}

public void Commit()
{
if (_transaction.IsActive)
_transaction.Commit();
}
}

Entity Framework 4.1 中的工作单元
public class SqlUnitOfWork : IUnitOfWork
{
private readonly ObjectContext _context;

public SqlUnitOfWork()
{
_context = new ObjectContext(connectionString);
_context.ContextOptions.LazyLoadingEnabled = true;
}

private SqlRepository<LogInfo> _logInfo = null;

public IRepository<LogInfo> LogInfos
{
get
{
if (_logInfo == null)
{
_logInfo = new SqlRepository<LogInfo>(_context);
}
return _logInfo;
}
}

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

使用 NHibernate 的存储库
public class NHibernateRepository<T> : IRepository<T> where T : class, IEntity
{
protected ISession Session;

public NHibernateRepository(ISession session)
{
Session = session;
}

public IQueryable<T> FindAll()
{
return Session.Query<T>();
}

public IQueryable<T> FindWhere(Expression<Func<T, bool>> predicate)
{
return Session.Query<T>().Where<T>(predicate);
}

public T FindById(int id)
{
return Session.Get<T>(id);
}

public void Add(T newEntity)
{
Session.Save(newEntity);
}

public void Remove(T entity)
{
Session.Delete(entity);
}
}

使用 Entity Framework 的存储库
public class SqlRepository<T> : IRepository<T> where T : class, IEntity
{
protected ObjectSet<T> ObjectSet;

public SqlRepository(ObjectContext context)
{
ObjectSet = context.CreateObjectSet<T>();
}

public IQueryable<T> FindAll()
{
return ObjectSet;
}

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

public T FindById(int id)
{
return ObjectSet.Single(i => i.Id == id);
}

public void Add(T newEntity)
{
ObjectSet.AddObject(newEntity);
}

public void Remove(T entity)
{
ObjectSet.DeleteObject(entity);
}
}

通过这个实现,我可以获得大部分功能,例如在 EF 和 NH 上工作的保存、删除、事务。但是当我开始编写针对 Repositories NH 的复杂 LINQ 查询时,大部分时间都失败了。当 Repository 返回 NhQueryable 时,OrderBy 和 ToList 等功能会引发错误。

下面的代码是从 ASP.NET MVC Controller 调用的,我使用 StructureMap 将 IUnitOfWork 实例注入(inject)到该 Controller 中。当注入(inject) NHibernateUnitOfWork 时,在注入(inject) SqlUnitOfWork 时,条件没有得到应用,因​​为它按预期工作。
var query = from a in _unitOfWork.AppInfos.FindAll()
join l in _unitOfWork.LogInfos.FindAll()
on a.Id equals l.ApplicationId
where l.Level == "ERROR" || l.Level == "FATAL"
group l by new { a.Id, a.ApplicationName } into g
select new LogInfoSummaryViewModel()
{
ApplicationId = g.Key.Id,
ApplicationName = g.Key.ApplicationName,
ErrorCount = g.Where(i => i.Level == "ERROR").Count(),
FatalCount = g.Where(i => i.Level == "FATAL").Count()
};
return query.AsEnumerable();

最佳答案

作为在 linq 之上不构建支持不同产品的解决方案的一方是灾难的方式。 Linq 和 IQueryable是有漏洞的抽象——每个 Linq 提供者都可以有自己的“特性”和限制。此外,EF 本身通过自定义扩展方法为 IQueryable 添加了一些逻辑。 (如 EFv4.1 中的 IncludeAsNoTracking)。这些方法在内部转换 IQueryable到 ORM 特定的类。

如果你想拥有通用的解决方案,你必须放弃 Linq 并添加第三种模式来形成抽象。除了存储库和工作单元模式之外,您还需要自定义 Specification图案。通常你会重新实现 NHibernate 的 Criteria API。

关于linq - 如何实现与 EF 和 NHibernate 一起使用的工作单元,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7411504/

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