【问题标题】:Multiply decimal and a double in Linq在Linq中乘以十进制和双精度
【发布时间】:2024-05-18 06:50:02
【问题描述】:

如果我有 poco 类

public class Entry
{
    public double Quantity { get; set; }
    public decimal Cost{ get; set; }
}

如何在 Linq 查询中对它们进行算术运算

context.Entries.Sum(e => (decimal)e.Quantity * e.Cost);

我无法将“System.Double”类型的对象转换为“System.Decimal”类型

编辑:我已将小数转换为 double 并且它有效。

context.Entries.Sum(e => e.Quantity * (double)e.Cost);

【问题讨论】:

  • 我没有看到这个异常调用 .Sum() 在一个带有一些手动构造的 Entry 实例的数组上。你有异常的堆栈跟踪吗?您可以提供更多代码上下文吗?
  • 按运算符优先级 Quantity 应转换为十进制并乘以 Cost(注意:如果您的查询是 LINQ to Entities,请使用 AsEnumerable)。您能提供异常详细信息和堆栈跟踪吗?
  • 只是一个想法(我知道它并没有真正提供答案):您可以通过将逻辑放在数据库中的存储过程中来解决该问题,该过程可以使用执行linq 到实体。

标签: c# entity-framework linq


【解决方案1】:

实体框架表明它不支持您想要的转换。要获取原始查询,您可以进行以下更改:

context.Entries
.AsEnumerable() // perform rest of work in memory
.Sum(e => (decimal)e.Quantity * e.Cost);

【讨论】:

  • 这会将表中的所有数据都带入内存!你至少应该做一个预测,只获取你要加在一起的列。
  • @MarcinJuraszek OP 不想进行投影,如果是这样,他只需添加一个 Where 子句。他的实体模型只有两个字段,所以我认为没有必要过滤列。
  • 不,这个查询比较复杂,我已经简化了很多问这个问题。我真的不想在内存中这样做。
【解决方案2】:

你可以使用 Convert.ToDecimal()

context.Entries.Sum(d => Convert.ToDecimal(d.Quantity)*d.Cost)

Here is working fiddle

如果您不使用可枚举集合,请按照 Tetsuya Yamamoto 所述进行编辑

context.Entries.ToList().Sum(d => Convert.ToDecimal(d.Quantity)*d.Cost)

【讨论】:

  • 如果 OP 的查询是 LINQ to Entities(不识别 ToDecimal 方法),这可能不起作用。在Sum 之前使用AsEnumerable 以确保安全。
【解决方案3】:

如果你坚持在数据库端执行所有计算并且你有强制转换的问题,你可以使用SqlFunctions类的静态方法,但当然会有性能开销:

var result = context.Entries
     .Sum(x => SqlFunctions.Exp(SqlFunctions.Log(x.Quantity) + SqlFunctions.Log(x.Cost)));

解释:e^(ln(Quantity) + ln(Cost)) = e^(ln(Quantity * Cost)) = Quantity * 费用

或者您可以尝试手动编写查询:

var result = context.Database
     .SqlQuery<decimal>("select sum(Quantity * Cost) from dbo.Entries)").FirstOrDefault();

【讨论】: