Entity Framework LINQ Query с использованием метода Custom C # Class - один раз да, один раз нет - потому что выполняется на клиенте или в SQL? - PullRequest
1 голос
/ 21 декабря 2010

У меня есть два написанных мной запроса Entity Framework 4 Linq, в которых используется метод пользовательского класса, один работает, а другой нет:

Пользовательский метод:

public static DateTime GetLastReadToDate(string fbaUsername, Discussion discussion)
{
 return (discussion.DiscussionUserReads.Where(dur => dur.User.aspnet_User.UserName == fbaUsername).FirstOrDefault() ?? new DiscussionUserRead { ReadToDate = DateTime.Now.AddYears(-99) }).ReadToDate;
}

Работающий запрос linq вызывает a from после a from, эквивалентный SelectMany ():

  from g in oc.Users.Where(u => u.aspnet_User.UserName == fbaUsername).First().Groups
  from d in g.Discussions
  select new
  {
   UnReadPostCount = d.Posts.Where(p => p.CreatedDate > DiscussionRepository.GetLastReadToDate(fbaUsername, p.Discussion)).Count()
  };

Не работающий запрос больше похож на обычный выбор:

  from d in oc.Discussions
  where d.Group.Name == "Student"
  select new 
  {
   UnReadPostCount = d.Posts.Where(p => p.CreatedDate > DiscussionRepository.GetLastReadToDate(fbaUsername, p.Discussion)).Count(),
  };

Я получаю ошибку:

LINQ to Entities does not recognize the method 'System.DateTime GetLastReadToDate(System.String, Discussion)' method, and this method cannot be translated into a store expression.

У меня вопрос: почему я могу использовать свой метод GetLastReadToDate () в первом запросе, а не во втором? Я полагаю, это как-то связано с тем, что выполняется на сервере БД, а что выполняется на клиенте? Эти запросы, похоже, используют метод GetLastReadToDate () так же, хотя, мне интересно, почему бы работать для первого, а не второго, и что наиболее важно, если есть способ факторизовать общий синтаксис запроса, как в методе GetLastReadToDate (), в отдельное местоположение для повторного использования в нескольких других запросах LINQ.

Обратите внимание, что все эти запросы используют один и тот же контекст объекта.

Ответы [ 2 ]

1 голос
/ 22 декабря 2010

Я думаю, вам лучше использовать Определенную моделью функцию здесь.

Определите скалярную функцию в вашей базе данных, которая возвращает DateTime , пропустите все, что вам нужно, сопоставьте ее с вашей моделью, а затем используйте в запросе LINQ:

from g in oc.Users.Where(u => u.aspnet_User.UserName == fbaUsername).First().Groups
  from d in g.Discussions
  select new
  {
   UnReadPostCount = d.Posts.Where(p => p.CreatedDate > myFunkyModelFunction(fbaUsername, p.Discussion)).Count()
  };
0 голосов
/ 21 декабря 2010

и, что наиболее важно, если есть способ разделить общий синтаксис запроса, такой как метод GetLastReadToDate (), в отдельное место для повторного использования в нескольких разных местах запросов LINQ.

Хранимая процедура, вероятно, была бы одним из способов сохранить этот «общий синтаксис запроса» ... EF, по крайней мере, 4.0, очень хорошо работает с SP.

...