#c# #linq
#c# #linq
Вопрос:
Мне нужен эквивалент этого оператора SQL в Linq, используя синтаксис метода / fluent.
SELECT u.[UserId], s.[UserId], d.[UserId]
FROM dbo.[Attachment] z
INNER JOIN dbo.[Activity] a ON z.[ActivityId] = a.[ActivityId]
INNER JOIN dbo.[Case] c ON a.[CaseId] = c.[CaseId]
INNER JOIN dbo.[CaseUser] x ON c.[CaseId] = x.[CaseId]
INNER JOIN dbo.[User] u ON x.[UserId] = u.[UserId]
LEFT OUTER JOIN dbo.[User] s ON u.[SupervisorId] = s.[UserId]
LEFT OUTER JOIN dbo.[User] d ON s.[SupervisorId] = d.[UserId]
WHERE u.[UserId] = @x OR s.[UserId] = @x OR d.[UserId] = @x
Кроме того, я использую его в контексте, где я должен вернуть System.Linq.Выражения.Объект выражения. Например, примером существующего, более простого кода может быть:
public override Expression<Func<Attachment, bool>> MatchingCriteria
{
get { return a => a.Activity.Case.CaseUsers.Any(x => (x.User.Id == this.id)); }
}
Я поставлен в тупик левыми соединениями, использующими синтаксис метода, который вычисляется как bool.
Ответ №1:
Я думаю, что следующее должно сработать… Вы проверяете, чтобы убедиться, что связанный объект в модели не равен null, а затем выполняете сравнение, если это не так:
return a => a.Activity.Case.CaseUsers
.Where(cu => cu.User.Id == this.id ||
(cu.User.Supervisor != null amp;amp;
cu.User.Supervisor.Id == this.Id) ||
(cu.User.Supervisor != null amp;amp;
cu.User.Supervisor.Supervisor != null amp;amp;
cu.User.Supervisor.Supervisor.Id == this.Id));
Комментарии:
1. Обратите внимание, что это не соединение и, следовательно, правильный пользователь не возвращается.
2. Что ж, я заменил WHERE на ANY, поскольку я, по сути, тестирую наличие идентификатора пользователя в цепочке пользователей. Кажется, это работает, но будет тестироваться дольше. Спасибо за предупреждение.
3. Я написал этот запрос, предполагая, что он не хочет возвращать пользователя. Я почти уверен, что сгенерированный SQL должен примерно соответствовать его запросу, но для проверки вам придется использовать ToTraceString() или Profiler.
Ответ №2:
Используя следующий метод, вы можете проверить, существует ли какой-либо из требуемых идентификаторов, и выбрать элемент.
С помощью примера определения класса, подобного:
class Foo
{
public int FirstBarId { get; set; }
public int SecondBarId { get; set; }
}
class Bar
{
public int BarId { get; set; }
}
Вы можете запросить, например:
var query = fooSet.Select(foo => new
{
Foo = foo,
Bar1 = barSet.FirstOrDefault(bar => foo.FirstBarId == bar.BarId),
Bar2 = barSet.FirstOrDefault(bar => foo.SecondBarId == bar.BarId)
})
.Where(x => x.Bar1 != null || x.Bar2 != null);
Комментарии:
1. На самом деле, рассматриваемый класс является рекурсивным: класс User { общедоступный пользовательский супервизор {get; set;}}
2. @alphadogg — Это ничего не меняет 🙂
3. Не так ли? Я имею в виду, что у вас есть два «независимых» дочерних элемента Bar для Foo, тогда как моя проблема заключается в том, как перейти на несколько уровней дочерних элементов?
4. @alphadogg — Переход на несколько уровней — это просто так. Вы можете легко расширить предоставленный мной запрос. Как вы думаете, в чем разница при замене barSet на fooSet?