鉴于两个类首先使用EF生成代码,并使用父子关系:
class Parent {
//...
public virtual ICollection<Child> Children
}
class Child {
//...
public decimal Amount{ get; set; }
public decimal UnitPrice { get; set; }
}
我想在Parent上创建一个属性Total
,类似于
decimal Total => Children.Sum(child => child.UnitPrice * child.Amount)
但是,如果我这样做,然后做
var list = ctx.Parents
.Where(p => p.Total > 1000)
.Select(p => new {
p.Id,
p.Total,
Count = p.Children.Count });
foreach(var item in list){
Console.WriteLine($"Id: {item.} ...");
}
我收到了错误
EntityFramework.SqlServer.dll中出现未处理的“System.NotSupportedException”类型异常
附加信息:LINQ to Entities不支持指定的类型成员“Total”。仅支持初始化程序,实体成员和实体导航属性。
虽然,在我看来,EF使用SUM(UnitPrice * Amount) as Total
生成查询并不难,但我无法让它发挥作用。
我已经尝试过像
这样的静态表达式 public static Expression<Func<Parent, decimal>> GetTotal()
{
return p=> p.Children.Sum(line => line.ItemQty * line.UnitPrice);
}
虽然只在代码中进行此计算是可以接受的。我想使用此示例来了解有关如何使用IQueryable的更多信息。
A Little Succes
在Parent
上给出以下静态属性 public static Expression<Func<Parent, decimal?>> Total =>
p=> (from c in p.Childeren
select c.UnitPrice * c.ItemQty).Sum();
然后做
var list = ctx.Parents.Select(Parent.Total);
我有一个包含所有总计的列表,我看到EF生成了以下查询
SELECT (SELECT SUM([Filter1].[A1]) AS [A1] FROM ( SELECT [Extent2].[UnitPrice] * CAST( [Extent2].[Amount] AS decimal(19,0)) AS [A1] FROM [dbo].[Child] AS [Extent2] WHERE [Extent1].[Id] = [Extent2].[ParentId] ) AS [Filter1]) AS [C1] FROM [dbo].[Parent] AS [Extent1]
因此,它确实能够将Sum()方法转换为SQL。现在我只需要在Where()中使用它。
答案 0 :(得分:1)
计算属性仅在类中已知,而不在数据库中。在访问这些计算出的属性之前,您需要实例化对象(到类中)。
要让它发挥作用并不难:
var list = ctx.Parents
.Where(p => p.Total > 1000)
.ToList() //This instantiates your data into objects
.Select(p => new {
p.Id,
p.Total,
Count = p.Children.Count });
这可能需要一个包含声明,具体取决于您是否有延迟加载:
var list = ctx.Parents
.Include(p => p.Children) //Children will be populated upon instantiation
.Where(p => p.Total > 1000)
.ToList() //This instantiates your data into objects
.Select(p => new {
p.Id,
p.Total,
Count = p.Children.Count });
虽然,在我看来,EF使用
SUM(UnitPrice * Amount) as Total
生成查询并不难,但我无法让它发挥作用。
还有比你提及的更多的东西。
什么的SUM
?不是当前结果(Parents
表),您需要在Children
表上完成计算的总和(按ParentId
分组),这是一个完全不同于你目前使用的数据集。
这就是为什么EF不会做你想做的事情。它试图决定查询的SELECT
部分,但您的期望需要更复杂的查询体;将孩子和父母聚集在一起以便对孩子进行计算,然后将这些结果归为一个值的方法。
如果您尝试自己编写SQL查询,那么您会发现 比仅仅SUM(UnitPrice * Amount) as Total
更复杂。