2012-01-31 3 views
0

У меня есть этот запрос Linq (не уверен, если его правильно), но то, что я хочу это:Linq - оптимизирует/исправить мой запрос

Возвращать все мои офисы компании (которые имеют отношение к моей компании, например CompanyID == mycompanyid) , которые заявили, что имеют почтовый индекс «cv», возвращают только офисы. (код для пояснения)

var offices = from office in _readOnlySession.All<Office>() 
.GetMyOffices(_userSession) //filter out my offices using extension method 
let postcodes = _readOnlySession.All<OfficePostCode>().Where(x => x.OfficeID == office.OfficeID) 
       .Join(_readOnlySession.All<PostCodeDistrict>().Where(r=> r.Region.ToLower().StartsWith("cv".ToLower())), 
          x => x.PostCodeID, 
          y => y.PostCodeID, 
          (x, y) => new { Region = y.Region }) 
where postcodes.Any() 
select new { office.OfficeID, office.Name }; 

Вопрос: как я могу сделать это всем методом запроса, более оптимизированным/правильным методом запроса?

Примечание: «резюме» будет переменная передается в метод - своего рода жёстко, чтобы проиллюстрировать мой пример

Update:

IQueryable<T> All<T>() where T : class, new(); 

    public IQueryable<T> All<T>() where T : class, new() 
    { 
     return GetTable<T>().AsQueryable(); 
    } 
+0

Не .Все взять Func в качестве параметра и возвращает логическое значение, а не перечислимый? Не похоже, что этот код будет компилироваться. – Bodrick

+0

@Bodrick - он компилируется и работает! – Haroon

+0

Я предполагаю, что вы используете там какой-нибудь метод расширения. Какой тип _readOnlySession? Does. All () просто возвращает все объекты из этой коллекции данного типа? – Bodrick

ответ

0

Вроде бы нормально. Только то, что может, но и не может работать лучше выполнять LET почтовых индексов части без условия OfficeID перед главным запросом, а затем использовать его в основном запросе, как:

where postcodes.Any(pc => pc.OfficeID == office.OfficeID) 
1

Я предположил, что OfficePostCode и Office оба имеют PostCodeID свойства , вам может потребоваться изменить последнее предложение .Where(), чтобы оно соответствовало вашим свойствам. Это должно делать то, что вы хотите, и IMO немного легче читать.

public IEnumerable<Office> GetOffices (string postCode) 
{ 
    List<Office> myOffices = _readOnlySession.All<Office>() 
     .GetMyOffices (_userSession) 
     .ToList(); // Get all the offices you are interested in. 


    List<OfficePostCode> postCodeDistricts = _readOnlySession 
     .All<OfficePostCode>() 
     .Where (x => x.Region.StartsWith (postCode, true, System.Globalization.CultureInfo.InvariantCulture)) 
     .ToList(); // A list of OfficePostCodes with the specified region. 

    // Using the 3 parameter overload for StartsWith lets you specify a case invariant comparison, 
    // which saves you from having to do .ToLower(). 

    return myOffices.Where (o => postCodeDistricts.Any (pcd => o.PostCodeID == pcd.PostCodeID)); 
} 

Конечно, вы можете уплотнить это вниз, удалив промежуточные переменные, но я лично считаю, это понятнее таким образом. Это также облегчает отладку, так как вы можете помещать контрольные точки на промежуточные переменные.

+0

Если это работает, он выглядит более эффективным. Нет анонимных объектов, которые создаются и уничтожают соединение. Плюс более читабельна. – weston

0

Что-то вроде этого, может быть?

var offices = _readOnlySession.All<Office>() 
    .GetMyOffices(_userSession) //filter out my offices using extension method 
    .Where(office => office.PostCodes.Any(pc => pc.District.Region.ToUpperInvariant().StartsWith("CV"))); 
Смежные вопросы