这个 SQL 查询能用 LINQ 实现吗?

3

我有一个简单的SQL查询,但是我在尝试用LINQ复制它时遇到了困难。

select top 1 * from tbl_CarTax tax
ORDER BY ABS(tax.C02_From - 286.0)

我尝试了下面的代码,但出现了错误... - LINQ to Entities不识别ToInt32(System.Object)方法,这个方法无法转换为存储表达式。

TaxCost = (from tax in db.DB2011_Vehicle_CarTax
orderby Math.Abs(Convert.ToInt32(C02Level - tax.C02_From))
select tax).SingleOrDefault();

非常感谢您的帮助。

Truegilly


1
C02Level和tax.C02_From属性的类型是什么? - SWeko
C02Leveltax.C02_Form的数据类型是什么?你可能遇到了数据类型转换的问题。 - Adriano Carneiro
C02Level 是一个 double 类型,tax.C02_From 是一个 int 类型 :) - JGilmartin
你正在使用Entity Framework吗? - sarvesh
2个回答

5

不需要使用Convert.ToInt。此外,FirstOrDefault相当于top 1。如果查询的结果返回多行,则SingleOrDefault会抛出异常。
尝试使用以下代码:

TaxCost = (from tax in db.DB2011_Vehicle_CarTax
           orderby Math.Abs(C02Level - tax.C02_From)
           select tax).FirstOrDefault();

与其他答案不同,我认为没有必要避免使用Math.Abs,因为Entity Framework知道这个方法并且可以将其转换为SQL。

1
如果他确实需要丢弃小数,可以调用 Math.Floor,这在 LINQ to EF 上也可以很好地转换。 - Diego
刚刚验证了 Linq to Entities 将 Math.Abs 转换为这个 Transact SQL 函数:ABS()。 - Nathan Prather

0
你可以拉取所有数据,然后在记录集上使用 Math.Abs(如果要拉取大量信息,则可能会很慢),或者你可以像这样做:
(from tax in db.DB2011_Vehicle_CarTax
 let level = C02Level - tax.C02_From
 let abs = (level < 0) ? (level * -1) : level
 orderby abs
 select tax).SingleOrDefault();

可能有更正式的方法来做这件事,但如果速度足够快,它应该可以工作。

编辑 - 实际上,看起来 Math.Abs 可以很好地转换为 SQL。如果您删除 Convert.Int32,它应该可以正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接