C# 如何使用NHibernate在存储库模式中进行复杂连接?
我正在使用存储库模式使用Nhibernate开发我的项目。如何在Nhibernate中进行复杂连接。我正在使用下面的存储库方法获取数据C# 如何使用NHibernate在存储库模式中进行复杂连接?,c#,nhibernate,C#,Nhibernate,我正在使用存储库模式使用Nhibernate开发我的项目。如何在Nhibernate中进行复杂连接。我正在使用下面的存储库方法获取数据 public virtual TEntity FindBy(Expression<Func<TEntity, bool>> query) { try { return NHUnitOfWork.Session.Query<TEntity>().Where(quer
public virtual TEntity FindBy(Expression<Func<TEntity, bool>> query)
{
try
{
return NHUnitOfWork.Session.Query<TEntity>().Where(query).FirstOrDefault();
}
catch (Exception ex)
{
throw;
}
}
公共虚拟空间查询(表达式查询)
{
尝试
{
返回NHUnitOfWork.Session.Query().Where(Query.FirstOrDefault();
}
捕获(例外情况除外)
{
投掷;
}
}
在这里,我可以获取数据,而无需任何连接。如何使用联接获取数据?
例如:菜单详细信息存储在菜单表中,菜单权限存储在菜单权限表中。如何为此创建存储库?使用
QueryOver
,接受输入Junction
,而不是Expression
,通过方法查找
下面的代码可能会有所帮助。如果您不需要,请删除列列表
和顶部
参数。请注意我的i会话
用法不同。您需要将nhSession
替换为NHUnitOfWork.Session
。另一个区别是,您在这里使用的是Query
,而我在这里使用的是QueryOver
public virtual IList<T> FindBy<T>(ProjectionList columnList, Junction where, int top) where T : BaseEntity
{
IList<T> instance = GetQueryOver<T>(columnList, where).Take(top).List();
return instance;
}
public virtual IQueryOver<T> GetQueryOver<T>(ProjectionList columnList, Junction where) where T : BaseEntity
{
IQueryOver<T> query = null;
if((columnList != null) && (where != null))
{
query = nhSession.QueryOver<T>()
.Select(columnList)
.TransformUsing(Transformers.AliasToBean<T>())
.Where(where);
}
else if((columnList != null) && (where == null))
{
query = nhSession.QueryOver<T>()
.Select(columnList)
.TransformUsing(Transformers.AliasToBean<T>());
}
else if((columnList == null) && (where != null))
{
query = nhSession.QueryOver<T>()
.Where(where);
}
else
{
query = nhSession.QueryOver<T>();
}
return query;
}
公共虚拟IList FindBy(ProjectionList columnList,Junction where,int top)其中T:BaseEntity
{
IList实例=GetQueryOver(columnList,其中).Take(top).List();
返回实例;
}
公共虚拟IQueryOver GetQueryOver(ProjectionList列列表,连接位置),其中T:BaseEntity
{
IQueryOver查询=null;
if((columnList!=null)&&(其中!=null))
{
query=nhSession.QueryOver()
.选择(列列表)
.TransformUsing(Transformers.AliasToBean())
.何处;
}
else如果((columnList!=null)&&(其中==null))
{
query=nhSession.QueryOver()
.选择(列列表)
.TransformUsing(Transformers.AliasToBean());
}
else if((columnList==null)和&(其中!=null))
{
query=nhSession.QueryOver()
.何处;
}
其他的
{
query=nhSession.QueryOver();
}
返回查询;
}
然后,您可以在其他位置调用它,如:
Junction where = Restrictions.Conjunction();
where.Add(Restrictions.Eq(Projections.Property<MyEntity>(x => x.Field), findValue));
where.Add(Restrictions.................);
where.Add(Restrictions.................);
entityList = Repository.FindBy<MyEntity>(null, where, 100);
连接,其中=限制。连接();
其中.Add(Restrictions.Eq(projects.Property(x=>x.Field)),findValue);
其中。添加(限制…………);
其中。添加(限制…………);
entityList=Repository.FindBy(null,其中,100);
如果您想快速加载相关实体,请使用Fetch
和FetchMany
public virtual Menu FindBy(Expression<Func<Menu, bool>> query)
{
return NHUnitOfWork.Session.Query<Menu>().Where(query)
.FetchMany(m => m.Rights)
// Required with FetchMany and First, otherwise only one right would be loaded.
.ToList()
.FirstOrDefault();
}
公共虚拟菜单查找方式(表达式查询)
{
返回NHUnitOfWork.Session.Query()。其中(查询)
.FetchMany(m=>m.Rights)
//FetchMany和First是必需的,否则将只加载一个权限。
托利斯先生()
.FirstOrDefault();
}
或者,如果您的模型每个菜单只有一个权限:
public virtual Menu FindBy(Expression<Func<Menu, bool>> query)
{
return NHUnitOfWork.Session.Query<Menu>().Where(query)
.Fetch(m => m.Right)
.FirstOrDefault();
}
public virtual TEntity FindBy<TFetched>(Expression<Func<TEntity, bool>> query,
Expression<Func<TEntity, TFetched>> fetch)
{
var query = NHUnitOfWork.Session.Query<TEntity>().Where(query);
if (fetch != null)
query = query.Fetch(fetch);
return query
.FirstOrDefault();
}
公共虚拟菜单查找方式(表达式查询)
{
返回NHUnitOfWork.Session.Query()。其中(查询)
.Fetch(m=>m.Right)
.FirstOrDefault();
}
但您似乎想定义一些封装NHibernate API的“通用存储库”。
也许那时:
public virtual TEntity FindBy<TFetched>(Expression<Func<TEntity, bool>> query,
Expression<Func<TEntity, IEnumerable<TFetched>>> fetchMany)
{
var query = NHUnitOfWork.Session.Query<TEntity>().Where(query);
if (fetchMany != null)
query = query.FetchMany(fetchMany);
return query
// Required with FetchMany and First, otherwise only one right would be loaded.
.ToList()
.FirstOrDefault();
}
通过(表达式查询、,
表达式(多个)
{
var query=NHUnitOfWork.Session.query().Where(query);
if(fetchMany!=null)
query=query.FetchMany(FetchMany);
返回查询
//FetchMany和First是必需的,否则将只加载一个权限。
托利斯先生()
.FirstOrDefault();
}
或者,如果您的模型每个菜单只有一个权限:
public virtual Menu FindBy(Expression<Func<Menu, bool>> query)
{
return NHUnitOfWork.Session.Query<Menu>().Where(query)
.Fetch(m => m.Right)
.FirstOrDefault();
}
public virtual TEntity FindBy<TFetched>(Expression<Func<TEntity, bool>> query,
Expression<Func<TEntity, TFetched>> fetch)
{
var query = NHUnitOfWork.Session.Query<TEntity>().Where(query);
if (fetch != null)
query = query.Fetch(fetch);
return query
.FirstOrDefault();
}
通过(表达式查询、,
表达式(获取)
{
var query=NHUnitOfWork.Session.query().Where(query);
if(fetch!=null)
query=query.Fetch(Fetch);
返回查询
.FirstOrDefault();
}
但如果需要多次回迁,该怎么办?和子回迁(ThenFetch
/ThenFetchMany
)?在我看来,这就像一条被诅咒的道路。您可能会按照该路径为整个NHibernateAPI编码封装
事实上,公开一个表达式,其中存储库上的
参数对我来说并不好。您的存储库不再负责定义如何查询数据。
如果要这样做,为什么不直接公开IQueryable
?与试图将其封装在一个“存储库”中,同时仍在这个“存储库”之外定义查询相比,它将证明代码的详细程度要小得多
*:当心笛卡尔积,以防执行多个FetchMany
。为了避免这种情况,可以将查询拆分为多个部分(如果您希望一次往返数据库,请使用ToFuture
),或者使用而不是提取。您确定此答案针对此问题吗?他正在使用Query
而不是QueryOver
并且不需要变压器。他可以使用AutoMapper中的选择
或项目到
,使投影更容易。