首先,我之前有一个问题,虽然看起来非常相似,但问题不一样,请看一下:Function import from SQL Server to Entity Framework runtime exception
此函数HammingDistance,用于在SQL Server中创建标量函数后运行良好,然后使用EDM函数映射导入实体框架。我一直在建立我的网站,在网站和EDMX周围做了一些分歧,但没有碰到这个功能并保证它的安全。这是SQL Server上的SQL函数:
ALTER function [dbo].[HammingDistance]
(@first bigint, @second bigint) returns int
as
begin
declare @xor bigint = @first ^ @second;
declare @one bigint = 1;
declare @diff int = 0;
declare @and bigint;
while (@xor != 0)
begin
set @and = @xor & @one;
if(@and = @one)
begin
set @diff = @diff + 1;
end
set @xor = @xor / 2;
end
return @diff;
end
这是我的C#代码:
声明:
public static class EdmFunctionMapping
{
[EdmFunction("MainDB.Store", "HammingDistance")]
public static int GetHammingDistance(long hash1, long hash2)
{
throw new NotSupportedException("This method can only be used in a LINQ-to-Entities query");
}
}
用法:
var query = (from p in VisibleObjects.OfType<Photo>()
let hd = EdmFunctionMapping.GetHammingDistance(targetPhoto.Analysis.Hash, p.Analysis.Hash)
let cd = Math.Abs(targetPhoto.Analysis.High.Red - p.Analysis.High.Red)+
Math.Abs(targetPhoto.Analysis.High.Green - p.Analysis.High.Green)+
Math.Abs(targetPhoto.Analysis.High.Blue - p.Analysis.High.Blue) +
Math.Abs(targetPhoto.Analysis.Low.Red - p.Analysis.Low.Red) +
Math.Abs(targetPhoto.Analysis.Low.Green - p.Analysis.Low.Green) +
Math.Abs(targetPhoto.Analysis.Low.Blue - p.Analysis.Low.Blue)
where
hd < 5 ||
(hd < 15 || cd < 100)
orderby hd ascending
select p).Take(50);
return query.ToList();
其中VisibleObjects不评估Enumerable。无论如何它在这里:
static IEnumerable<GlobalObject> VisibleObjects
{
get
{
return from obj in db.GlobalObjectSet where obj.IsVisible && !obj.SiteUser.IsDeactivated orderby obj.ID descending select obj;
}
}
大概两三个星期以前的一切都工作了,在那个时间间隔内我添加/删除了很多东西,并没有检查汉明距离是否有效,所以我不知道它什么时候破坏了。它不再起作用,就像EdmFunction属性不存在一样,试图在我的应用程序中进行评估并抛出我写的异常,说它只能用于L2E查询。我已经对所有内容进行了双重检查,甚至完全重新创建了数据库并从EDMX生成,并使用数据库中的更新模型创建并导入了该函数,并且它在EDMX中看到了该函数,并且它(显然)在EDMX文件中可用SSDL部分如:
<Function Name="HammingDistance" ReturnType="int" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="true" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">
<Parameter Name="first" Type="bigint" Mode="In" />
<Parameter Name="second" Type="bigint" Mode="In" />
</Function>
但是当涉及到应用程序时,它就不会映射到EDM!多次尝试,从头开始创建所有数据库,没有任何变化,它会在query.ToList()
中抛出异常,并且没有内部异常(它有意义,因为它抛出我自己的异常,不应该由应用程序执行)。我不知道问题的根源,我错过了一些明显的东西吗?
答案 0 :(得分:3)
如果它无法识别您的Edm映射函数,请确保您不会在某处意外将查询更改为linq-to-objects,因为这正是您可以看到该错误的原因。要验证这一点,只需尝试创建另一个测试查询,它将直接实体访问并调用您的函数。类似的东西:
long hash = targetPhoto.Analysis.Hash;
var query = from p in db.GlobalObjectSet.OfType<Photo>()
select new { EdmFunctionMapping.GetHammingDistance(hash, p.Analysis.Hash) };
如果这样的查询通过,你肯定有我提到的问题。
修改强>
我想我现在看到了问题。您的VisibleObjects
返回IEnumerable
=&gt; LINQ到对象。试试这个:
public static IQueryable<GlobalObject> GetVisibleObjects(this IQueryable<GlobalObject> query)
{
return from obj in query
where obj.IsVisible &&
!obj.SiteUser.IsDeactivated
orderby obj.ID descending
select obj;
}
并调用您的方法:
from p in db.GlobalObjectSet.GetVisibleObjects().OfType<Photo>() ...