Как использовать пользовательское свойство в запросе LINQ-to-Entities? - PullRequest
16 голосов
/ 11 февраля 2010

У меня есть класс Post, который является Entity Framework моделью. Он содержит свойство, подобное этому:

public bool Showable {
  get {
    return this.Public && this.PublishedDate > DateTime.now
  }
}

Я могу использовать его в таком запросе:

from p in db.Posts where p.Showable select p;

но когда у меня есть свойство, которое использует его, как это

public IEnumerable<Post> ShowablePosts {
  get {
    return from p in db.Posts where p.Showable select p;
  }
}

тогда я не могу сделать:

from p in ShowablePosts where p.Id > 42 select p;

Там написано:

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

Ответы [ 3 ]

20 голосов
/ 11 февраля 2010

Вы можете сделать это, если напишите свойство как Expression, которое переводится в SQL.

Вот как это сделать.

Это немного сложно, потому что это общее решение сложной проблемы.

Общая идея такова: LINQ to Entities (например, все LINQ провайдеры) не может преобразовать скомпилированный код, такой как ваше свойство, в SQL во время выполнения. LINQ to Objects может выполнить скомпилированный код, но не может перевести его. Но они могут перевести Expression<T>. Чтобы вы могли написать:

public static Expression<Func<Post, bool>> WhereActive
{
    get
    {
        return p => p.Public && p.PublishedDate > DateTime.Now;
    }
}

Тогда вы могли бы написать:

public IEnumerable<Post> ShowablePosts 
{
    get 
    {
        return db.Posts.Where(WhereActive);
    }
}

... и LINQ to Entities может перевести это. Код в посте, на который я ссылаюсь, обобщает эту идею.

1 голос
/ 11 февраля 2010

К сожалению, Entity Framework просто не поддерживает вычисляемые свойства (то есть свойство, которое возвращает вычисленное значение, а не ссылку на вспомогательное поле), но оно может быть поддержано в будущем.

0 голосов
/ 30 ноября 2016

Я думаю, что самый простой способ сделать это - использовать атрибут Computed пакета DelegateDecompiler.EntityFramework, упомянутый в этого ответа .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...