2015-12-03 3 views
8

У меня есть LINQ к Entities запросМогу ли я использовать CAST внутри запроса LINQ to Entities?

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

Могу ли я указать EF, что я хочу, чтобы применить cast к прейскурантной, прежде чем запрашивать и материализовать его ? Может быть, что-то вроде EntityFunctions.Cast? Или я могу использовать функцию ESQL cast?

Я хочу LINQ для создания запроса SQL вдоль этих линий

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

Моя цель избавиться от кучки точности/масштабе запроса. Поскольку есть десятичное вычитание и деление, результат математики является десятичной (38, 26)! Это больше, чем .NET может обрабатывать и больше, чем мне нужно.

+0

Разве вы не можете использовать 'членов Convert'? –

+0

@AmitKumarGhosh 'Convert.ToDecimal' не распознается EF –

+1

Единственными функциями, которые я знаю, являются [SqlFunctions] (https://msdn.microsoft.com/en-us/library/system.data.objects.sqlclient.sqlfunctions % 28v = vs.110% 29.aspx). Ваши роли в этих функциях отсутствуют. – tschmit007

ответ

2

EF позволяет сопоставить функции CLR с функциями базы данных, используя атрибут DbFunction. К сожалению, это выглядит как встроенный в cast и convert не являются функциями и это не выглядит, как вы можете отобразить их.

Вместо этого вы можете создать UDF, который делает бросок и отобразить его в DbModel. API сопоставления сложный, поэтому я бы использовал библиотеку Code First Functions, чтобы сделать это за вас. (Если вы используете базу данных первой или модель первой, вы можете сделать отображение вручную в вашем SSDL и CSDL). Кроме того, нет никакого способа сделать динамическое кастинг внутри UDF, поэтому вам нужно будет выбрать отдельные функции для каждого выбранного броска. Вот пример для 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)) 
}; 

Смотрите эту blog post или эту MSDN статью для более подробной информации.