Если это не база данных, а простые сущности на стороне клиента, вы можете скомпилировать свое выражение, вы можете использовать его как метод, который принимает User и возвращает bool:
Expression<Func<User, bool>> nameIsBob = u => u.Name == "Bob";
Func<User, bool> compiledNamedIsBob = nameIsBob.Compile();
var query3 = something.Events
.Where(e => compiledNameIsBob(e.User))
Это будет извлеките ваш Expression<Func<User, bool>>
, извлеките из него Func<User, bool>
и создайте Expression<Func<Event, bool>>
, где Func<Event, bool>
извлекает пользователя события и вызывает Func<User, bool>
, используя его ..
ВАЖНО : этот совет по компиляции Expression to Fun c не работает на чем-то похожем на структуру сущностей. EF возьмет записанное выражение. NET и переведет его в SQL, и, хотя это может быть достаточно умным, он не будет использовать автономный метод. NET (полученный от компиляции выражения в Забавьте c, выше) и разберите его на части, переводя составляющие его утверждения в SQL. Единственный способ, которым это может сработать, - это загрузить всю таблицу БД в клиент, а затем вызвать метод. NET для каждой загруженной записи (если не было выполнено работы, чтобы EF отправлял метод. NET в SQLServer, компилируем он там и вызывается как часть запроса. NET функции могут существовать на SQL сервере, но EF этого не делает)
Итак ...
Вы должны понимать, что ctx.Events.Where()
занимает Expression<Func<Event, bool>>
, и у вас есть Expression<Func<User, bool>>
-> вам нужно создать выражение, которое работает с событиями:
Expression<Func<Event, bool>> eventUserNameIsBob = e => e.User.Name == "Bob";
, что вы также можете сделать для события как вы сделали для пользователя:
//like you did this
Expression<Func<User, bool>> nameIsBob = u => u.Name == "Bob";
Expression<Func<User, bool>> isActive = u => u.Active;
//you can do this
Expression<Func<Event, bool>> eventUserNameIsBob = e => e.User.Name == "Bob");
и примените, как вы применяете к таблице пользователя:
var query1 = ctx.Users.Where(nameIsBob); //returns Users
var query2 = ctx.Users.Where(isActive); //returns Users
var query3 = ctx.Events.Where(eventUserNameIsBob).Select(e => e.User); //returns Users, via the Select
Однако, если вы хотите иметь только выражение nameIsBob
, а не eventUserNameIsBob
выражение Вы должны понимать, что nameIsBob
выражение работает только для запрашиваемых коллекций Users , поэтому вам нужно взять все ваши события и выкопать из них пользователей, а также запустить выражение на раскопанном Пользователи, что означает, что вы по существу потеряли Новость вашего события (вы должны получить его обратно, спросив пользователя):
var query4 = ctx.Events.Select(e => e.User).Where(nameIsBob);
Этот действительно возвращает вам "группу пользователей", как и другие запросы (* 1040) *), но вы потеряли событие, если не получите его обратно от пользователя:
var query4 = ctx.Events.Select(e => e.User).Where(nameIsBob).Select(u => u.Event);
Что будет делать ваша БД в этом случае, я не уверен; вам придется проверить это / записать в журнал сгенерированные SQL.
Лично я бы сделал новое выражение, которое понимает события, как указано выше (eventUserNameIsBob
), иначе я бы не стал передавать выражения вокруг, и я будет просто определять их в строке:
var query3 = ctx.Events.Where(e => e.User.Name == "Bob"); //events owned by bobs
Современные ORM БД могут распаковать это, чтобы стать SELECT events.* FROM events JOIN users ON (...) WHERE users.name = 'bob'
, а не в былые времена, где это будет выглядеть так:
SELECT id FROM users WHERE name = 'bob' --returns list of 1,2,4,5
SELECT * FROM events WHERE userid = 1
SELECT * FROM events WHERE userid = 2
SELECT * FROM events WHERE userid = 4
SELECT * FROM events WHERE userid = 5