Могу ли я использовать CAST внутри запроса LINQ to Entities?
У меня есть запрос LINQ to Entities
From item In ctx.Items
Select new {
ListPrice = item.Cost / (1M - item.Markup)
};
Могу ли я указать EF, что я хочу применить cast
к прейскуранту, прежде чем запрашивать и реализовывать его1? Есть ли что-то вроде EntityFunctions.Cast
может быть? Или я могу использовать ESQL cast
функционировать?
Я хочу, чтобы LINQ генерировал SQL-запрос по этим направлениям.
SELECT cast((Cost / (1 - Markup)) as decimal(10, 2)) AS ListPrice
1 Моя цель - избавиться от кучности точности / масштабирования запроса. Поскольку есть десятичное вычитание и деление, результатом математики является десятичное число (38, 26)! Это намного больше, чем может справиться.NET, и больше, чем мне нужно.
1 ответ
EF позволяет отображать функции CLR в функции базы данных, используя DbFunction
приписывать. К сожалению, это выглядит как встроенный cast
а также convert
не являются функциями, и это не похоже, что вы можете сопоставить их.
Вместо этого вы можете создать UDF, который выполняет приведение и отображать его в DbModel
, API отображения сложен, поэтому я бы использовал библиотеку Code First Functions, чтобы сделать это для вас. (Если вы сначала используете базу данных или модель, вы можете выполнить сопоставление вручную в SSDL и CSDL 1). Кроме того, нет никакого способа выполнять динамическое приведение внутри 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))
};
1 См. Этот блог или статью MSDN для более подробной информации.