C# 使用方法在LINQ中投影嵌套DTO
假设我们有以下实体:C# 使用方法在LINQ中投影嵌套DTO,c#,nhibernate,linq-to-nhibernate,C#,Nhibernate,Linq To Nhibernate,假设我们有以下实体: public class Customer { public virtual int Id { get; set; } public virtual string FirstName { get; set; } public virtual string LastName { get; set; } } 此外,还有以下扩展方法: public static string GetCard(this Customer @this) {
public class Customer
{
public virtual int Id { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
}
此外,还有以下扩展方法:
public static string GetCard(this Customer @this)
{
throw new InvalidOperationException("Use only in IQueryable");
}
现在,我要执行以下查询:
var q = from c in this.Session.Query<Customer>()
select new { Id = c.Id, InfoCard = c.GetCard() };
var q=this.Session.Query()中的c
选择新{Id=c.Id,InfoCard=c.GetCard()};
我认为创建和注册以下hql生成器就足够了:
class GetCardGenerator : BaseHqlGeneratorForMethod
{
public GetCardGenerator()
{
SupportedMethods = new[]
{
ReflectionHelper.GetMethodDefinition(() => CustomerExtensions.GetCard(null))
};
}
public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
{
Expression<Func<Customer, Card>> definition = c => new Card
{
FirstName = c.FirstName,
LastName = c.LastName,
FullName = c.FirstName + " " + c.LastName
};
return visitor.Visit(definition);
}
}
类GetCardGenerator:basehqlGeneratorFormMethod
{
公共GetCardGenerator()
{
SupportedMethods=new[]
{
ReflectionHelper.GetMethodDefinition(()=>CustomerExtensions.GetCard(空))
};
}
公共重写HqlTreeNode BuildHql(MethodInfo方法、表达式targetObject、只读集合参数、HqlTreeBuilder treeBuilder、IHqlExpressionVisitor)
{
表达式定义=c=>新卡
{
FirstName=c.FirstName,
LastName=c.LastName,
全名=c.FirstName+“”+c.LastName
};
回访者。访问(定义);
}
}
不幸的是,异常NotSupportedException与消息MemberInit一起引发。在调查期间,我在Linq\Visitors\SelectClauseHqlNominator.cs中发现HQL不支持New和MemberInit表达式的评论
我的问题是:是否有可能创建将在LINQ查询的select子句中使用并用于创建和填充DTO对象的方法
更新:我不想让IQueryable从IQueryable变为IQueryable,但我正在寻找一种解决方案,允许我在任何地方从客户那里提取卡片,例如,我有一个订单实体引用客户,我想调用如下查询:
from o in this.Session.Query<Order>
select new { Amount = o.OrderAmount, Customer = o.Customer.GetCard() };
this.Session.Query中的来自o的
选择new{Amount=o.OrderAmount,Customer=o.Customer.GetCard()};
目前,您要求的东西不容易实现,因为为了处理投影,NHibernate使用HQL之外的ClientSideResultOperator(请参见。VisitSelectClause
方法)
例如,下面的查询
var q = from c in this.Session.Query<Customer>()
select new Card
{
FirstName = c.FirstName,
LastName = c.LastName,
FullName = c.FirstName + " " + c.LastName
};
查询将转换为
var q = from c in this.Session.Query<Customer>()
select new
{
Id = c.Id,
InfoCard = new Card
{
FirstName = c.FirstName,
LastName = c.LastName,
FullName = c.FirstName + " " + c.LastName
})
};
var q=this.Session.Query()中的c
选择新的
{
Id=c.Id,
信息卡=新卡
{
FirstName=c.FirstName,
LastName=c.LastName,
全名=c.FirstName+“”+c.LastName
})
};
目前,您要求的东西不容易实现,因为为了处理投影,NHibernate使用HQL之外的ClientSideResultOperator(请参见。VisitSelectClause
方法)
例如,下面的查询
var q = from c in this.Session.Query<Customer>()
select new Card
{
FirstName = c.FirstName,
LastName = c.LastName,
FullName = c.FirstName + " " + c.LastName
};
查询将转换为
var q = from c in this.Session.Query<Customer>()
select new
{
Id = c.Id,
InfoCard = new Card
{
FirstName = c.FirstName,
LastName = c.LastName,
FullName = c.FirstName + " " + c.LastName
})
};
var q=this.Session.Query()中的c
选择新的
{
Id=c.Id,
信息卡=新卡
{
FirstName=c.FirstName,
LastName=c.LastName,
全名=c.FirstName+“”+c.LastName
})
};
我是这样做的,但在第三位写同一段代码并不有趣;)@诺瓦科夫看到了更新。希望这会有所帮助。稍后我将尝试回答原始问题。谢谢,我将尝试使用DelegateDecompiler解决方案,它看起来很不错:)我是这样做的,但在第三位编写相同的代码并不有趣;)@诺瓦科夫看到了更新。希望这会有所帮助。稍后我将尝试回答原始问题。谢谢,我将尝试使用DelegateDecompiler解决方案,它看起来很不错:)
var q = (from c in this.Session.Query<Customer>()
select new { Id = c.Id, InfoCard = c.GetCard() }).Decompile();
[Decompile]
public static string GetCard(this Customer @this)
{
return new Card
{
FirstName = @this.FirstName,
LastName = @this.LastName,
FullName = @this.FirstName + " " + @this.LastName
};
}
var q = from c in this.Session.Query<Customer>()
select new
{
Id = c.Id,
InfoCard = new Card
{
FirstName = c.FirstName,
LastName = c.LastName,
FullName = c.FirstName + " " + c.LastName
})
};