linq to entities не распознает метод
у меня есть эти методы:
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 ответов
при использовании linq-to-entities вы не можете использовать произвольные методы .NET в запросе. Каждый метод, используемый в запросе, должен быть переведен на SQL. Это не поможет вам вернуться Expession<Func<entityType, bool>>
потому что условие where должно быть оценено для каждой записи на сервере базы данных.
для EF ваш код означает что-то вроде:
SELECT COUNT(*)
FROM ...
LEFT JOIN ...
WHERE IsMatch(....)
поскольку EF проверяет имена функций, переданных в запрос, он выдаст исключение, потому что он не знает эквивалент IsMatch на SQL сервер.
единственными возможными функциями, которые могут использоваться в Linq-to-entities, являются:
- функции Cannonical с предопределенным сопоставлением с эквивалентом SQL
EdmFunctions
EdmFunctions-это методы, отмеченные EdmFunctionAttribute
карты .Чистая функция в SQL аналог. Эти функции обычно не могут быть выполнены в общем коде .NET, потому что они ничего не делают или вызывают исключение. Они только держатель места функции для Linq-to-сущностей. Доступные функции EdmFunctions:
- предопределенные EdmFunctions в
System.Data.Objects.EntityFunctions
- предопределенные EdmFunctions для SQL Server (не компактный) в
System.Data.Objects.SqlClient.SqlFunctions
- пользовательские сопоставленные функции SQL-мастер импорта в Entity designer позволяет импортировать функции SQL (кроме функций с табличным значением). После этого вы можете написать пользовательскую статическую функцию .NET и сопоставить ее с помощью
EdmFunction
атрибут функции SQL, импортированной в дизайнер. - пользовательские функции, определенные моделью - это специальная функция, написанная вручную в файле EDMX (открыт как XML). Это пользовательская многоразовая часть Entity SQL.
Я уже описал как создать модель определенной функции в другой ответ. Создание сопоставляется функция SQL довольно похожа. Вместо ручного создания Function
элемент в EDMX вы будете отображать EdmFunctionAttribute
свойства импортированной функции SQL.
вы передаете выражение, которое вызывает функцию с именем IsMatch
.
LINQ to Entities не знает, что делать с этой функцией.
Я имел дело с подобной проблемой. Рабочее решение использовало .AsEnumerable()
перед попыткой использовать мой пользовательский метод. Ты можешь!--2-->посмотри тут.
На самом деле, то, что вы передаете для подсчета, выглядит так:
bool anonymous_delagate#123(T entity)
{
return entity.IsMatch(a,b,c,d)
}
но для этого потребуется EF, чтобы узнать, какой на самом деле метод IsMatch
, что называется на этом существе, значит.
единственное, о чем я могу думать сейчас, это использовать какую-то динамическую обработку выражений для создания этого запроса dynamicaly. Или переработайте свой дизайн на что-то другое.
На самом деле, есть более простой и нормальный метод, который требует нескольких шагов чтобы сделать.
- сделать метод
IsMatch
статический. - возвращение
Expression<{your entity here}, bool>
непосредственно сIsMatch
. - передайте это так:
({your entity here}.IsMatch({parameters}))
отдых может оставаться таким же, как сейчас.
Edit: Example Это будет работать с конкретным объектом, поэтому я буду asume ваш объект ордер. Замените свою собственную сущность.
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));