2011-08-20 32 views
2

首先,我有一個先前的問題前一段時間,這雖然看起來很相似,是不一樣的問題,看看吧:Function import from SQL Server to Entity Framework runtime exception實體框架EdmFunction進口不被識別

此功能, 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()中的異常,並且沒有內部異常(這很有意義,因爲它引發了我自己的異常,應該不會執行該異常。我不知道問題的根源,我是否錯過了明顯的東西?

回答

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 => linq-to-objects。在db.GlobalObjectSet.OfType ()其中EdmFunctionMapping.GetHammingDistance

from p in db.GlobalObjectSet.GetVisibleObjects().OfType<Photo>() ... 
+0

是的,使用簡單的查詢,如'VAR的查詢=從號碼:試試這個:

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; } 

,並致電法像(p.Analysis.Hash,targetPhoto.Analysis。哈希)<5選擇p;'工作。那麼問題出在哪裏呢?我使用的方法就是我在那裏發佈的所有內容,只有常規的數學函數,VisibleObjects(我已經發布)和GetHammingDistance(現在似乎不是問題的原因。) 。 –

+1

我添加了一些更多的信息。你的查詢是linq-to-objects。 –

+0

是的,我現在才知道,並沒有意識到我正在使用IEnumerable而不是IQueryable,因爲我的數據集不是很大(不影響性能),而HammingDistance是我依賴於SQL Server本身的唯一函數。 。將其更改爲IQueryable,它工作。 –