无法识别实体框架EdmFunction导入

本文关键字:EdmFunction 导入 框架 实体 识别 | 更新日期: 2023-09-27 18:06:05

首先,我之前有一个问题,虽然看起来很相似,但不是同样的问题,看看它:函数从SQL Server导入到实体框架运行时异常

在SQL Server中创建标量函数,然后使用EDM函数映射导入实体框架后,这个函数HammingDistance可以很好地工作。我一直在建设我的网站,在网站和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();

where 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()中抛出异常,并且没有内部异常(这是有意义的,因为它抛出了我自己的异常,不应该由应用程序执行)。我不知道问题的根源,我是不是错过了什么明显的东西?

无法识别实体框架EdmFunction导入

如果它不能识别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 => linq-to-objects。试试这个:
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>() ...