简体   繁体   English

我可以在LINQ to Entities查询中使用CAST吗?

[英]Can I use a CAST inside a LINQ to Entities query?

I have a LINQ to Entities query 我有一个LINQ to Entities查询

From item In ctx.Items
Select new {
    ListPrice = item.Cost / (1M - item.Markup)
};

Can I specify to EF that I want it to apply a cast to the list price before querying and materializing it 1 ? 我可以指定EF,我希望它应用cast查询和物化它1日前标价? Is there something like EntityFunctions.Cast maybe? 是否有类似EntityFunctions.Cast东西? Or can I use the ESQL cast function? 或者,我可以使用ESQL cast功能?

I want the LINQ to generate a SQL query along these lines 我希望LINQ能够沿着这些方向生成SQL查询

SELECT cast((Cost / (1 - Markup)) as decimal(10, 2)) AS ListPrice

1 My goal is to get rid of a bunch of precision/scale the query. 1我的目标是摆脱一堆精度/缩放查询。 Because there's decimal subtraction and division, the result of the math is a decimal(38, 26)! 因为有十进制减法和除法,所以数学结果是小数(38,26)! That's way more than .NET can handle and more than I need. 这比.NET可以处理的更多,而且超出了我的需要。

EF allows you to map CLR functions to database functions using the DbFunction attribute. EF允许您使用DbFunction属性将CLR函数映射到数据库函数。 Unfortunately, it looks like the built in cast and convert are not functions and it does not look like you can map to them. 不幸的是,它看起来像内置的castconvert不是功能,它并不像你可以映射到它们。

Instead you can create a UDF which does the cast and map it in the DbModel . 相反,您可以创建一个UDF来执行转换并将其映射到DbModel The mapping API is complicated so I would use the Code First Functions library to do it for you. 映射API很复杂,所以我会使用Code First Functions库为您完成。 (If your using Database first or Model first, you can do the mapping manually in your SSDL and CSDL 1 ). (如果您首先使用数据库或首先使用模型,则可以在SSDL和CSDL 1中手动执行映射)。 Also, there's no way to do dynamic casting inside a UDF so you'll need to pick write separate functions for each cast you want. 此外,无法在UDF中进行动态转换,因此您需要为每个所需的转换选择单独的函数。 Here's an example for a cast(field as decimal(10,4) . 这是cast(field as decimal(10,4)的例子cast(field as decimal(10,4)

-- In SQL Server
CREATE FUNCTION ClrRound_10_4
(
    @value decimal(28, 10)
)
RETURNS decimal(10,4)
AS
BEGIN
    DECLARE @converted decimal(10,4)

    SELECT @converted = cast(round(@value, 4) as decimal(10,4))

    RETURN @converted

END
GO
//In your DbContext class
using CodeFirstStoreFunctions;

public class MyContext : DbContext {
    protected override void OnModelCreating(DbModelBuilder builder) {
        builder.Conventions.Add(new FunctionsConvention("dbo", typeof(Udf));
    }

    //etc
}

//In a static class named Udf (in the same namespace as your context)
using System.Data.Entity;

public static class Udf {
    [DbFunction("CodeFirstDatabaseSchema", "ClrRound_10_4")]
    public static decimal ClrRound_10_4(decimal value) {
        throw new InvalidOperationException("Cannot call UDF directly!");
    }
}

//In your LINQ query
from item in ctx.Items
select new {
    ListPrice = Udf.ClrRound_10_4(item.Cost / (1M - item.Markup))
};

1 See this blog post or this MSDN article for more details. 1有关更多详细信息,请参阅此博客文章或此MSDN文章。

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

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