C# 具有不同根实体类型的QueryOver ProjectionList

C# 具有不同根实体类型的QueryOver ProjectionList,c#,nhibernate,fluent-nhibernate,queryover,C#,Nhibernate,Fluent Nhibernate,Queryover,我在试图重用NHibernate QueryOvers中的投影列表时遇到了问题。我不知道如何为不同的根实体重用东西 对象模型大致表示为: 早餐一对多糕点多对零或一咖啡 这两个独立的查询大致如下: session.QueryOver() .Where(b=>b.Id==searchId) .Inner.JoinQueryOver(b=>b.糕点,()=>糕点) .Left.JoinAlias(p=>p.Coffee,()=>Coffee) .选择(投影) .TransformUsing(Trans

我在试图重用NHibernate QueryOvers中的投影列表时遇到了问题。我不知道如何为不同的根实体重用东西

对象模型大致表示为:

早餐一对多糕点多对零或一咖啡

这两个独立的查询大致如下:

session.QueryOver()
.Where(b=>b.Id==searchId)
.Inner.JoinQueryOver(b=>b.糕点,()=>糕点)
.Left.JoinAlias(p=>p.Coffee,()=>Coffee)
.选择(投影)
.TransformUsing(Transformers.AliasToBean())
.List();
session.QueryOver()
.Where(c=>c.Id==searchId)
.Inner.JoinQueryOver(c=>c.糕点,()=>pastry)
.选择(投影)
.TransformUsing(Transformers.AliasToBean())
.List();
我尝试重用的常见投影如下所示:

public ProjectionList GetSharedProjections(Coffee coffeeAlias)
{
    /* Same as above except with "coffeeAlias"
}
session.QueryOver<Coffee>(() => coffee)
    .Select(GetSharedProjections(() => coffee));
var projections=projections.ProjectionList()
.Add(projects.Property(()=>pastry.Name,()=>target.PastryName))
.Add(projects.Property(()=>coffee.Name,()=>target.CoffeeName));
这些使用别名的投影在第一个查询(root:breaken)中工作得很好,因为它们不试图提取根实体上的属性。在第二个查询(root:Coffee)中,它爆炸性地说它在Coffee上找不到'Coffee.Name',因为它不喜欢别名。QueryOver(()=>coffee)语法没有帮助,因为它实际上没有将“coffee”注册为别名,它只是将其用于类型推断。哦,该死的,这就是问题所在。有一个愚蠢的应用程序基础架构正在破坏别名语法,而不是实际使用下面的别名版本

第二个查询希望投影看起来像:

var projections=projections.ProjectionList()
.Add(projects.Property(()=>pastry.Name,()=>target.PastryName))
.Add(projects.Property(c=>c.Name,()=>target.CoffeeName));
但是,这现在与第一个查询不兼容


是否有任何方法可以实现这一点,这样我就可以在不知道根实体类型的情况下投影属性?

我认为您需要做的就是在
会话中分配
coffee
别名。QueryOver
调用:

Coffee coffee = null;

session.QueryOver<Coffee>(() => coffee)
    /* etc */
然后有一些代码调用了助手方法:

session.QueryOver<Coffee>(() => coffee)
    .Select(GetSharedProjections());
然后传入您的别名:

session.QueryOver<Coffee>(() => coffee)
    .Select(GetSharedProjections(coffee));
然后,您可以将
getSharedProject
方法更改为采用表达式形式的别名:

public ProjectionList GetSharedProjection(Expression<Func<Coffee>> coffeeAlias)
{
    TargetDTO target = null; 

    var projections = Projections.ProjectionList()
        .Add(BuildProjection<Coffee>(coffeeAlias, c => c.CoffeeName))
            .WithAlias(() => target.CoffeeName);
}
public ProjectionList GetSharedProjection(表达式coffeeAlias)
{
TargetDTO target=null;
var projections=projections.ProjectionList()
.Add(BuildProjection(coffeeAlias,c=>c.CoffeeName))
.WithAlias(()=>target.CoffeeName);
}
现在,调用您的方法如下所示:

public ProjectionList GetSharedProjections(Coffee coffeeAlias)
{
    /* Same as above except with "coffeeAlias"
}
session.QueryOver<Coffee>(() => coffee)
    .Select(GetSharedProjections(() => coffee));
session.QueryOver(()=>coffee)
.选择(GetSharedProject(()=>coffee));
当有人更改你的别名时,你就被覆盖了。您还可以在许多查询中安全地使用此方法,而不必担心别名变量的实际名称

免责声明:以下是我个人博客的链接


您可以通过这种方式找到有关构建查询的更多信息。

这正是解决方案!我以前试过这个,但我发现我的应用程序有愚蠢的自定义基础设施包装NHibernate调用,这打破了QueryOver(()=>废话)的别名版本。我知道别名的问题,深入研究NHibernate实现很有趣。我已经在使用表达式作为解决方法。其他新闻:哇。你的博客是我成功地与QueryOver合作的唯一原因,现在你在这里回答我的问题。谢谢!:-)