简体   繁体   English

EF Core 3.1 拥有对象的属性总和失败

[英]EF Core 3.1 Sum of owned object's properties is failing

It worked in 2.1 but started failing on 3.1它在 2.1 中有效,但在 3.1 中开始失败

System.InvalidCastException: 'Unable to cast object of type 'System.Linq.Expressions.NewExpression' to type 'System.Linq.Expressions.MethodCallExpression'.'
var ordersCounts = await ordersCountsQuery 
       .Select(x => new TransactionDTO
       {
            Value = new MoneyDTO(ordersCountsQuery.Sum(a => a.TotalPrice.Amount)) // worked perfectly on 2.1
       })
       .FirstOrDefaultAsync();

a.TotalPrice.Amount is decimal on Sql server database a.TotalPrice.Amount在 Sql 服务器数据库上为decimal

In EF Core 2.1 I have set it up在 EF Core 2.1 我已经设置了

.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning))

It looks like you may be hitting this breaking change between 2.2 and 3.0 versions of the entity framework:看起来您可能在实体框架的 2.2 和 3.0 版本之间遇到了这种重大变化:

https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-3.0/breaking-changes#linq-queries-are-no-longer-evaluated-on-the-client https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-3.0/break-changes#linq-queries-are-no-longer-evaluated-on-the-客户

Old behavior旧行为

Before 3.0, when EF Core couldn't convert an expression that was part of a query to either SQL or a parameter, it automatically evaluated the expression on the client.在 3.0 之前,当 EF Core 无法将作为查询一部分的表达式转换为 SQL 或参数时,它会自动在客户端上计算表达式。 By default, client evaluation of potentially expensive expressions only triggered a warning.默认情况下,客户端对可能昂贵的表达式的评估只会触发警告。

New behavior新行为

Starting with 3.0, EF Core only allows expressions in the top-level projection (the last Select() call in the query) to be evaluated on the client.从 3.0 开始,EF Core 仅允许在客户端评估顶级投影(查询中的最后一个 Select() 调用)中的表达式。 When expressions in any other part of the query can't be converted to either SQL or a parameter, an exception is thrown.当查询的任何其他部分中的表达式无法转换为 SQL 或参数时,将引发异常。

If this is the case, you'll have to re-write your query to suit (this may have to be two separate queries).如果是这种情况,您必须重新编写查询以适应(这可能必须是两个单独的查询)。


I would note that your query seems to be a bit strangely structured:我会注意到您的查询结构似乎有点奇怪:

var ordersCounts = await ordersCountsQuery 
   .Select(x => new TransactionDTO
   {
        Value = new MoneyDTO(ordersCountsQuery.Sum(a => a.TotalPrice.Amount)) // worked perfectly on 2.1
   })
   .FirstOrDefaultAsync();

Get a list of MoneyDTO (one for every item in the query), each one containing the sum of the total list and select the first.获取 MoneyDTO 列表(查询中的每个项目一个),每个列表包含总列表和第一个 select 的总和。

The following would do the same and likely be slightly more performant (only returning a single value:以下将执行相同的操作,并且可能会稍微提高性能(仅返回一个值:

var totalPrice = ordersCountsQuery.Sum(a => a.TotalPrice.Amount);

var orderCounts = new TransactionDTO
{
    Value = new MoneyDTO(totalPrice) 
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM