Импорт Entity Framework EdmFunction не распознается - PullRequest
2 голосов
/ 20 августа 2011

Прежде всего, у меня был предыдущий вопрос некоторое время назад, который, хотя и кажется очень похожим, но НЕ та же самая проблема, взгляните на него: Импорт функций из SQL Server в Entity Framework исключение времени выполнения

Эта функция, HammingDistance, хорошо работала после создания скалярной функции в SQL Server, а затем импортировалась в Entity Framework с использованием сопоставления функций EDM.Я продолжал строить свой сайт, сделал некоторые различия вокруг сайта и EDMX, но не затронул функцию и сохранил ее в безопасности.Вот SQL-функция на 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, создал и импортировал функцию, используя Update Model from Database, и она видит функцию в 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(), и нет внутреннего исключения (это имеет смысл, поскольку выдает мое собственное исключение, которое НЕ должно выполняться приложением).Я понятия не имею об источнике проблемы, я упускаю что-то очевидное?

1 Ответ

3 голосов
/ 20 августа 2011

Если она не распознает вашу сопоставленную функцию 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) }; 

Если такой запрос пройдет, у вас определенно будет проблема, о которой я упоминал.

Edit:

Мне кажется, я вижу проблему сейчас. Ваш 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>() ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...