Линк к сущностям не распознает метод - PullRequest
10 голосов
/ 01 мая 2011

У меня есть эти методы:

   public int count(
        Guid companyId, Expression<Func<T, bool>> isMatch)
    {
        var filters = new Expression<Func<T, bool>>[]{
            x => x.PriceDefinition.CompanyId == companyId,
            isMatch
        };

        return GetCount(filters);
    }

public virtual int GetCount(
            IEnumerable<Expression<Func<T, bool>>> filters)
        {
            IQueryable<T> _query = ObjectSet;

            if (filters != null)
            {
                foreach (var filter in filters)
                {
                    _query = _query.Where(filter);
                }
            }

           return _query.Count();
        }

При использовании:

count(some_guid, x => x.IsMatch(entityId, inviterId, routeId, luggageTypeId));

я получаю следующее исключение:

LINQ to Entities does not recognize the method 'Boolean IsMatch(System.Nullable`1[System.Int64], System.Nullable`1[System.Int64], System.Nullable`1[System.Int64], System.Nullable`1[System.Int64])' method, and this method cannot be translated into a store expression.

В чем причина этого?
Как я могу это решить?

Ответы [ 4 ]

14 голосов
/ 01 мая 2011

При использовании linq-to-entity вы не можете использовать произвольные методы .NET в запросе. Каждый метод, используемый в запросе, должен быть переведен в SQL. Это не поможет вам вернуть Expession<Func<entityType, bool>>, потому что, где условие должно быть оценено для каждой записи на сервере базы данных.

Для EF ваш код означает что-то вроде:

SELECT COUNT(*)
FROM ...
LEFT JOIN ...
WHERE IsMatch(....) 

Поскольку EF проверяет имена функций, переданные в запрос, он выдаст исключение, потому что он не знает эквивалент IsMatch на сервере SQL.

Единственные возможные функции, которые можно использовать в Linq-to-entity:

EdmFunctions - это методы, отмеченные EdmFunctionAttribute, который отображает функцию .NET на аналог SQL. Эти функции обычно не могут быть выполнены в общем коде .NET, потому что они ничего не делают или выдают исключение. Они являются только функциональным заполнителем для Linq-to-entity. Доступные функции Edm:

  • Предопределенные функции Edm в System.Data.Objects.EntityFunctions
  • Предопределенные функции Edm для SQL Server (не компактные) в System.Data.Objects.SqlClient.SqlFunctions
  • Пользовательские сопоставленные функции SQL - мастер импорта в конструкторе Entity позволяет импортировать функции SQL (кроме функций с табличными значениями). После этого вы можете написать собственную статическую функцию .NET и сопоставить ее по атрибуту EdmFunction с функцией SQL, импортированной в конструктор.
  • Функции, определяемые пользовательской моделью - это специальная функция, написанная вручную в файле EDMX (открывается в формате XML). Это настраиваемая повторно используемая часть Entity SQL.

Я уже описал , как создать определенную моделью функцию в другом ответе. Создание сопоставленной функции SQL очень похоже на . Вместо того, чтобы вручную создавать элемент Function в EDMX, вы сопоставите свойства EdmFunctionAttribute с импортированной функцией SQL.

2 голосов
/ 01 мая 2011

Вы передаете выражение, которое вызывает функцию с именем IsMatch.

LINQ to Entities не знает, что делать с этой функцией.

1 голос
/ 01 мая 2011

Я имел дело с подобной проблемой.Рабочее решение использовало .AsEnumerable(), прежде чем пытаться использовать мой пользовательский метод.Вы можете взглянуть на это здесь .

0 голосов
/ 01 мая 2011

На самом деле то, что вы передаете для подсчета, выглядит как эта функция:

bool anonymous_delagate#123(T entity)
{
    return entity.IsMatch(a,b,c,d)
}

Но для этого EF необходимо знать, что на самом деле означает метод IsMatch, который вызывается для этой сущности.

Единственное, о чем я могу подумать сейчас, - это использовать какое-то динамическое подделывание выражений для динамического создания этого запроса.Или переделайте свой дизайн в другое.

На самом деле, существует более простой и нормальный метод, для выполнения которого требуется несколько шагов.

  1. Сделайте метод IsMatch статическим.
  2. Возврат Expression<{your entity here}, bool> непосредственно из IsMatch.
  3. Передать как: ({your entity here}.IsMatch({parameters}))

Остальные могут остаться такими же, как сейчас.

Редактировать: Пример Это будет работать с конкретной сущностью, поэтому я предполагаю, что ваша сущность Order .Замените свою собственную сущность.

public static Expression<Func<Order, bool>> IsMatch(int id, ...) // static method, that returns filtering expression
{
     return i => i.Id == id; // create the filtering criteria
}

Затем назовите ее так:

count(some_guid, Order.IsMatch(entityId, inviterId, routeId, luggageTypeId));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...