Могу ли я создать запрос LINQ-to-Entity для полей, не являющихся членами Entity - PullRequest
1 голос
/ 13 апреля 2011

У меня есть класс Entity, который я расширил, используя синтаксис partial class, чтобы иметь некоторые производные свойства.Я хотел бы выполнить запрос с использованием интерфейса IQueryable<T>, который использует информацию из этих полей, но в настоящее время я получаю исключение, в котором говорится

Указанный элемент типа 'Заголовок' не поддерживается в LINQсущностям.Поддерживаются только инициализаторы, элементы сущностей и свойства навигации сущностей.

Вот соответствующие фрагменты кода.Вы можете предположить, что объект Entity имеет элемент String с именем Id.

public partial class MyEntityObject
{
   public String Title { get { return MyStrings.ResourceManager.GetString(Id) ?? ""; } }
}

/**
 * Throws exception trying to sort on the 'Title' field of a 'MyEntityObject'
 */
public IEnumerable<T> Query<T>(String fieldName, int low, int high)
{
   // Get the ObjectContext<T> using a Repository pattern
   var query = context.GetRepository<T>()

   // Create an OrderBy clause based on the field by dynamically building an expression tree
   //  see /3123470/pomogite-s-linq-i-generics-ispolzovanie-getvalue-vnutri-zaprosa
   PropertyInfo propertyInfo = typeof(T).GetProperty(fieldName);

   ParameterExpression e = Expression.Parameter(typeof(T), "e");
   MemberExpression mexpr = Expression.MakeMemberAccess(e, propertyInfo);

   IQueryable<T> sortedQuery = query.OrderBy(Expression.Lambda<Func<T,Object>>(mexpr, e));
   return sortedQuery.Skip(low).Take(high - low + 1).AsEnumerable();
}

В качестве последнего средства я всегда могу сделать AsEnumerable() перед Skip и Take, но это будет включать в себя извлечение всех объектов из базы данных дажеесли выбор может быть сделан с помощью SQL.

Возможно, лучшая альтернатива - это использовать отражение, чтобы проверить, что свойство объекта имеет DataMemberAttribute, а затем выбрать либо query.OrderBy().Skip().Take().AsEnumerable(), либо query.AsEnumerable().OrderBy().Skip().Take()? * 1023.*

1 Ответ

3 голосов
/ 13 апреля 2011

Нет, вы не можете, потому что запрос linq-to-entity - это просто дерево выражений, переведенное в SQL.Чтобы перевести дерево в SQL, используется ваше сопоставление сущностей, и поскольку Title не входит в ваше сопоставление, оно выдаст исключение.

Вызов AsEnumerable перед Skip и Take звучит очень плохо, потому чтоон всегда будет передавать содержимое всей таблицы данных в ваше приложение.Это будет очень медленно и в случае больших таблиц данных также бесполезно.

Если это проблема локализации, ваша база данных должна содержать локализованные строки, чтобы сделать это эффективным.В то же время, если вам нужно сделать это только с несколькими записями, вы можете загрузить их все.

...