У меня есть несколько запросов (в проекте C #), которые все используют один и тот же синтаксис объединения, есть ли простой способ переместить объединение из запроса в «функцию» или «шаблон» (из-за отсутствияболее подходящее слово).
Текущий запрос выглядит следующим образом (rc - мой ObjectContext)
var x =
from b in rc.Pressures
join g in rc.GUIDIdentityMaps on b.UserIdentity equals g.UserIdentity
where g.UserId == userId
orderby b.Recorded descending
select b;
Я хотел бы иметь возможность взять объединение и поместить его в 'функция 'называется что-то вроде' PressuresJoin '
from b in rc.Pressures
join g in rc.GUIDIdentityMaps on b.UserIdentity equals g.UserIdentity
where g.UserId == userId
, а затем используется что-то вроде
var x = PressuresJoin()
orderby b.Recorded descending
select b;
Обновление: Следуя указаниям @Xanatos', я создал функцию IQueryable, напримерthis.
public static IQueryable<Pressure> PressuresJoin(ObjectContext rc, Guid userId)
{
return from b in rc.Pressures
join g in rc.GUIDIdentityMaps on b.UserIdentity equals g.UserIdentity
where g.UserId == userId
select b;
}
, который я затем использовал следующим образом
IQueryable<Pressure> q = PressuresJoin(rc, userId);
var y =
from b in q
orderby b.Recorded descending
select b;
, поэтому использование IQueryable теперь означает, что мне не нужно писать один и тот же код соединения снова и снова, и при этомМне нужно убедиться, что значения давления, поступающие из БД, ограничены правильным пользователем (так как PressuresJoin гарантирует, что это всегда происходит).
Обратите внимание, что мне не нужно было создавать дополнительный класс (как это предлагается), потому чтоМне не нужен GUIDIdentityMaps information ПОСЛЕ объединения.
Очень аккуратно и опрятно - спасибо всем участникам
Обновление II: После ответа, предоставленного Кирком, я отошел от 'Синтаксис ручного соединения и просмотр с использованием свойства навигации.
Это привело меня к нескольким вариантам выбора. Первым было использовать .Include так
public static IQueryable<Pressure> PressuresJoinInclude(ObjectContext rc, Guid userId)
{
return from b in rc.Pressures.Include("GuidIdentityMap")
where b.GUIDIdentityMap.UserId == userId
select b;
}
и называть его так:this
IQueryable<Pressure> q = PressuresJoinInclude(rc, userId);
var y =
from b in q
orderby b.Recorded descending
select b;
Это работает просто великолепно (поэтому ответ Киркс также является ответом), но мне не очень нравится синтаксис .Include (string), и он поймал меня, поскольку я неправильно написалGUIDIdentityMap.
Затем я посмотрел на способы избежать использования .Include (строка) и придумал
public static IQueryable<Pressure> PressuresJoinDirect(ObjectContext rc, Guid userId)
{
return from b in rc.GUIDIdentityMaps.Single(i => i.UserId == userId).Pressures.AsQueryable()
select b;
}
замечать AsQueryable () в конце (приведение его из IEnumerable обратно).в IQueryable) Это называется как
IQueryable<Pressure> q = PressuresJoinDirect(rc, userId);
var y =
from b in q
orderby b.Recorded descending
select b;
Пока что я думаю, что это мой любимый, хотя было бы лучше, если бы Pressures был «первым» объектом в выражении вместо GUIDIdentityMaps, но я непроверил, чтобы увидеть, что SQПроизводится L или какие есть различия в производительности (если есть)
Теперь я собираюсь посмотреть на решение Jims. (Точка).
Обновление III: Надеюсь, я правильно понял точечную запись, и вот мое «объединение» с использованием навигации, уже встроенной в объекты.Моя функция IQueryable выглядит следующим образом
public static IQueryable<Pressure> PressuresJoinDot(ObjectContext rc, Guid userId)
{
return from b in rc.Pressures
where b.GUIDIdentityMap.UserId == userId
select b;
}
, и использовать ее так же просто, как и другие
IQueryable<Pressure> q = PressuresJoinDot(rc, userId);
var y =
from b in q
orderby b.Recorded descending
select b;
В конце всего этого я делаю Пропустить / Взять вот так
IQueryable<Pressure> z = y.Skip(startRow).Take(rows);
List<Pressure> l = z.ToList();
Все четыре вышеуказанные опции работают, и конечным результатом любого из этих запросов является один и тот же набор записей.К моему удивлению, они не все генерируют один и тот же SQL, и они не все работают с одинаковой скоростью (поэтому я разделил Skip / Take и ToList ()).
Простой старый Join иТочечная версия работает с одинаковыми скоростями, с простым присоединением, возможно, немного быстрее.Версия «Включить» работает хорошо, но количество операций чтения из БД увеличивается при переходе к списку записей.Прямой метод очень медленный, более чем в 10 раз по сравнению с другими методами, и я уверен, что Skip / Take выполняется для сгенерированного List (), а не для базы данных.
Конечно, мои глаза открылисьнасколько легко было бы выбрать неправильный LINQ и, конечно, выбрать его на основании того, что он выглядит «самым красивым», метод Direct, не будет лучшей идеей.