2014-12-09 2 views
0

Я использую Entity Framework. Следующий класс представляет таблицу из базы данных.Можно ли получить эти данные с помощью одного запроса linq?

public partial class TermBucket 
{ 
    public short ID { get; set; } 
    public byte Period { get; set; } 
    public byte Min { get; set; } 
    public byte Max { get; set; } 
} 

PK - это идентификатор и период, поэтому в таблице может быть несколько идентификаторов.

При запросе объекта у меня есть в моем распоряжении период + время (число, связанное с периодом). Период устанавливается как перечисление, поэтому я хотел бы использовать его как:

Time: 3 
Period: 3 (Days) 

То, что я хочу сделать, это найти ведро, которое соответствует требованиям, а затем получить все записи для этого ведра. Вот что я в настоящее время сделать:

Шаг 1: Получить ID

return r.Find() // this is my repository 
    .AsNoTracking() 
    .Where(x => (int)tp.Period == x.Period && tp.Time >= x.Min && tp.Time <= x.Max) 
    .Select(x => x.ID) 
    .Single(); 

Шаг 2: Получить все записи для ID, используя извлеченную ID

return r.Find() 
    .AsNoTracking() 
    .Where(x => x.ID == ID); 

Итак, есть 2 различных запросов, но можно ли получить эти данные за один раз?

+0

Возможно, вы можете просто вложить первый запрос во второй? Вы пробовали что-то вроде ответов, найденных здесь: http://stackoverflow.com/questions/5354050/nested-select-linq-query – MaxRev17

+0

Да просто объедините предикаты, используя &&, '.Where (x => (int) tp. Период == x.Period && tp.Time> = x.Min && tp.Time <= x.Max && x.ID == ID) ' –

ответ

0

Не можете ли вы просто объединить их?

return r.Find() 
    .AsNoTracking() 
    .Where(x => x.ID == r.Find() 
     .AsNoTracking() 
     .Where(x => (int)tp.Period == x.Period && tp.Time >= x.Min && tp.Time <= x.Max) 
     .Select(x => x.ID) 
     .Single()); 
+0

Извините за наивность Руфус-Линк, как правило, меня дезориентируют. Похоже, это может сработать - я отдам это. – dotnetnoob

0

Вы можете сделать это, используя соединение. Пример

public partial class TermBucket 
    { 
     public short ID { get; set; } 
     public byte Period { get; set; } 
     public byte Min { get; set; } 
     public byte Max { get; set; } 
    } 

    static void Main(string[] args) 
    { 
     List<TermBucket> l = new List<TermBucket>(); 
     l.Add(new TermBucket() { ID = 1, Period = 3, Min = 10, Max = 14 }); 
     l.Add(new TermBucket() { ID = 1, Period = 4, Min = 10, Max = 13 }); 
     l.Add(new TermBucket() { ID = 1, Period = 5, Min = 100, Max = 25 }); 
     l.Add(new TermBucket() { ID = -1, Period = 3, Min = 10, Max = 12 }); 

     int period = 3; 
     int minV = 10; 
     int maxV = 13; 
     var res = from e in l 
        join e2 in l on e.ID equals e2.ID 
        where e.Period == period && minV >= e.Min && maxV <= e.Max 
        select e2; 

     foreach (var r in res) 
     { 
      Console.WriteLine(r.ID + " " + r.Period); 
     } 

     Console.ReadLine(); 
    } 

Выведет

1 3 
1 4 
1 5 
0

Да, это:

return r.Find() 
    .AsNoTracking() 
    .Where(x => x.ID == r.Find() 
    .AsNoTracking() 
    .Where(x => (int)tp.Period == x.Period && tp.Time >= x.Min && tp.Time <= x.Max) 
    .Select(x => x.ID) 
    .Single()); 

Но я рекомендовал бы разбить его на два запросов, так как у вас уже есть, чтобы обработать случай где первый запрос не возвращает никаких результатов. (Так оно и есть, в настоящее время .Single() генерирует исключение, если .Select() пуст).

Смежные вопросы