Как я могу динамически настроить POCO-прокси в EF 4? - PullRequest
1 голос
/ 29 марта 2011

Я хотел бы динамически настроить некоторые классы POCO, переопределяя себя на виртуальных членах, чтобы иметь возможность компилировать запросы LINQ to Entities. Я знаю о событии ObjectMaterialized, но это происходит после создания экземпляра класса. Я хотел бы иметь возможность создать прокси-сервер самостоятельно, переопределить виртуальных членов, которых я хочу, и затем передать их в EF, это возможно?

Представьте себе следующий класс POCO:

public class Consumer {
    /* That´s a virtual property with an association in EF */
    public virtual ICollection <Message> Messages { get; set; }

    /* That´s the business logic I would like to optimize. */
    public virtual Message GetMyLatestMessage()
    {
        return Messages.Where(m => m.Writer != null && m.Writer.ID == ID && m.Type == "Message")
                       .OrderByDescending(m => m.Date)
                       .Take(1)
                       .FirstOrDefault();
    }
 }

Когда я использую этот код против EF 4, выражение внутри GetMyLatestMessage() становится запросом SQL, но я хотел бы предварительно скомпилировать эти выражения, потому что некоторые из них каждый раз анализируются довольно медленно.

1 Ответ

2 голосов
/ 29 марта 2011

EF не предлагает перехватывать или заменять динамический прокси, сгенерированный для POCO. Кроме того, то, что вы показываете, не может быть оптимизировано, потому что это Linq-to-Objects. EF всегда загружает все сообщения в память при первом запуске. Именно так работают свойства навигации и отложенная загрузка, и это, вероятно, также является причиной проблем с производительностью.

Если вы хотите провести оптимизацию, исключите ваш GetMyLatestMessage из Consumer для разделения класса и используйте:

public Message GetLatestMessage(int consumerId)
{
    return context.Messages.Where(m => m.Consumer.Id == consumerId &&
                                       m.Writer != null && 
                                       m.Writer.ID == ID && 
                                       m.Type == "Message")
                  .OrderByDescending(m => m.Date)
                  .Take(1)
                  .FirstOrDefault();

}
...