C# 如何使用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

我正在使用存储库模式使用Nhibernate开发我的项目。如何在Nhibernate中进行复杂连接。我正在使用下面的存储库方法获取数据

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中的
选择
项目到
,使投影更容易。