Pri*_*ERO 7 c# linq entity-framework
我有许多工作实体框架标量函数.但是,当我尝试通过标量函数返回'truthy'值时,我得到以下异常:
"ETC.Operations.DbClient.DbClient.Data.DbClientContext"类型上指定的方法"Boolean svfn_CanCloneDocument(Int32,System.String)"无法转换为LINQ to Entities存储表达式.
我试过将RETURN TYPE改为......
为什么这会失败?
打电话看起来像:
public IQueryable<ShakeoutDataItem> Query()
{
var uow = UnitOfWork as DbClientUnitOfWork;
var dbContext = UnitOfWork.DbContext as DbClientContext;
var query = (from document in dbContext.vDocumentStatus
join shakeout in uow.Shakeout on document.DocumentId equals shakeout.DocumentId
join shakeoutDetail in uow.ShakeoutDetail on shakeout.Id equals shakeoutDetail.ShakeoutId
join meter in uow.Meter on shakeoutDetail.MeterId equals meter.Id
join product in uow.Product on shakeout.ProductId equals product.Id into productLEFTJOIN
from product in productLEFTJOIN.DefaultIfEmpty()
// THIS FAILS
let cloneable = dbContext.svfn_CanCloneDocument(document.DocumentId, "SHAKEOUT")
select new ShakeoutDataItem()
{
// Other fields LEFT OUT for BREVITY
CanClone = cloneable
});
return query.OrderBy(x => x.DocumentCreatedDate).ThenBy(x => x.SchedulingBatch);
}
Run Code Online (Sandbox Code Playgroud)
让我们看起来像:
[Function(FunctionType.ComposableScalarValuedFunction, nameof(svfn_CanCloneDocument), Schema = "dbo")]
[return: Parameter(DbType = "bit")]
public bool svfn_CanCloneDocument(int documentId, string documentTypeShortName)
{
ObjectParameter documentIdParameter = new ObjectParameter("documentId", documentId);
ObjectParameter documentTypeShortNameParameter = new ObjectParameter("documentTypeShortName", documentTypeShortName);
return this.ObjectContext().ExecuteFunction<bool>(nameof(this.svfn_CanCloneDocument), documentIdParameter, documentTypeShortNameParameter).SingleOrDefault();
}
Run Code Online (Sandbox Code Playgroud)
SQL看起来像:
CREATE FUNCTION [dbo].[svfn_CanCloneDocument]
(
@DocumentId INT,
@DocumentTypeShortName NVARCHAR(50)
)
RETURNS BIT
AS
BEGIN
/*
Name: [dbo].[svfn_CanCloneDocument]
Creation Date: 02/02/2019
Purpose: Retrieves the Full Name for given User.Id or returns NULL
Input Parameters: @DocumentId = The Id for the DOCUMENT record
@DocumentTypeShortName = The Short Name for the DOCUMENT TYPE record
Format: @DocumentId = 1
@DocumentTypeShortName = SHAKEOUT
*/
DECLARE @Value BIT = CAST(0 AS BIT);
-- NOTE: They are going to have more DOCUMENT TYPES later-on. If the rules for Cloneable are the same...simplify this function
IF(@DocumentTypeShortName = 'SHAKEOUT')
BEGIN
DECLARE @Id INT = (SELECT TOP 1 Id FROM [dbo].[tvfn_ListDocumentDescendants](@DocumentId) WHERE Id <> @DocumentId ORDER BY Id DESC);
-- CAN CLONE When no Descendants Exist
SELECT @Value = (CASE
WHEN @Id IS NULL THEN CAST(1 AS BIT)
ELSE CAST(0 AS BIT)
END)
END
-- Return the result of the function
RETURN @Value
END
Run Code Online (Sandbox Code Playgroud)
我有很多工作实体框架标量函数
问题是,在LINQ to Entities查询中使用的此数据库上下文中是否还有其他可用的自定义标量函数?
您专注于bool
返回类型,但异常消息指示未映射函数(当 LINQ 查询使用无法转换为 SQL 的未知自定义方法时,EF6 会引发相同的异常)。
正如在将函数添加到实体模型中提到的:
在调用任何代码之前先调用函数,
FunctionConvention
或者FunctionConvention<TFunctions>
必须添加到DbModelBuilder
的DbContext
,函数使用的复杂类型也是如此
您需要将以下行添加到您的DbClientContext
类OnModelCreating
覆盖中:
modelBuilder.Conventions.Add(new FunctionConvention<DbClientContext>());
Run Code Online (Sandbox Code Playgroud)
忘记这样做可以让您在 LINQ to Entities 查询之外使用像这样的标量函数,例如
var result = dbContext.svfn_CanCloneDocument(...);
Run Code Online (Sandbox Code Playgroud)
但在 LINQ to Entities 查询中使用时会导致上述运行时异常。
通过注册它们FunctionConvention
可以正确处理后面的场景。