2009-03-02 2 views
1

Я довольно новичок в LINQ в целом, но до сих пор мне удалось выяснить, что мне нужно/нужно. Ниже приведенный ниже запрос LINQ2SQL дает желаемые результаты, в которых есть объекты местоположения, каждый из которых имеет свой собственный набор единиц. Начальные объявления переменных выполняются для установки значений, которые мне нужны для запроса, и не должны иметь отношение к моей проблеме, но необходимы для контекста.Насыщение дочерней коллекции с помощью запроса LINQ

Проблема, с которой я сталкиваюсь, заключается в том, что существует более 400 местоположений, а в текущем случае у меня есть структурированный запрос, он попадает в базу данных для каждого из них вместо одного большого запроса. Это приводит к тому, что производительность сильно страдает, принимая 30 с лишним секунд, чтобы получить полный результат, что неприемлемо. У меня есть SQL-запрос хранимой процедуры, который возвращает результаты всего за секунду или два.

Есть ли способ реструктурировать этот запрос, чтобы я не попадал в базу данных для каждого местоположения? Я уверен, что это вызвано дополнительным «ToList()» в подзапросе Units, но я не знаю, как формировать результат без ToList(). Любая настройка производительности будет ОГРОМНОЙ помощью. Спасибо за любую помощь!

Dim curNames1 = (From ons In dc.organization_names _ 
    Where ons.eff_date <= ssDate _ 
    Order By ons.eff_date Descending _ 
    Group ons By ons.organization_id Into gNames = Group _ 
    Select New With { _ 
    Key .Key = organization_id, _ 
    .Result = gNames.Take(1)}) _ 
    .SelectMany(Function(a) (a.Result)) 

Dim curLocs1 = (From oLocs In dc.organization_locations _ 
    Where oLocs.eff_date <= ssDate _ 
    Order By oLocs.eff_date Descending _ 
    Group oLocs By oLocs.organization_id Into gLocs = Group _ 
    Select New With { _ 
    Key .Key = organization_id, _ 
    Result = gLocs.Take(1)}) _ 
    .SelectMany(Function(a) (a.Result)) 

Dim curStatuses1 = (From oEDate In dc.organization_conversion_dates _ 
    Where oEDate.edate <= ssDate _ 
    Order By oEDate.edate Descending _ 
    Group oEDate By oEDate.organization_id Into gEDates = Group _ 
    Select New With { _ 
    Key .Key = organization_id, _ 
    .Result = gEDates.Take(1)}) _ 
    .SelectMany(Function(a) (a.Result)) 

Dim curCommand1 = (From oCommand In dc.organization_service_assigneds _ 
    Where oCommand.eff_date <= ssDate _ 
    Order By oCommand.eff_date Descending _ 
    Group oCommand By oCommand.organization_id Into gCmds = Group _ 
    Select New With { _ 
    Key .Key = organization_id, _ 
    .Result = gCmds.Take(1)}) _ 
    .SelectMany(Function(a) (a.Result)) 

Dim curComponent1 = (From oCompo In dc.organization_compos _ 
    Where oCompo.eff_date <= ssDate _ 
    Order By oCompo.eff_date Descending _ 
    Group oCompo By oCompo.organization_id Into gCompos = Group _ 
    Select New With { _ 
    Key .Key = organization_id, _ 
    .Result = gCompos.Take(1)}) _ 
    .SelectMany(Function(a) (a.Result)) 

ss.Locations = New ObservableCollection(Of Location)((_ 
    From map In dc.MapBackgrounds Where map.MapID = options.Map _ 
    Let Locs = map.Schemes.SchemeLocations _ 
    From SchemeLoc In Locs _ 
    Where (options.Locations.Count = 0 Or _ 
     options.Locations.Contains(SchemeLoc.Location.ID)) _ 
    Select New Location With { _ 
    .ID = SchemeLoc.Location.ID, .Name = SchemeLoc.Location.Location, _ 
    .Y = SchemeLoc.Y, .X = SchemeLoc.X, _ 
    .Country = New Country With _ 
    {.ID = SchemeLoc.Location.Countries.ID, _ 
    .Name = SchemeLoc.Location.Countries.country}, _ 
    .State = If(SchemeLoc.Location.State = -1, Nothing, _ 
    New USState With {.ID = SchemeLoc.Location.States.ID, _ 
    .Name = SchemeLoc.Location.States.state, _ 
    .Abbreviation = SchemeLoc.Location.States.state}), _ 
    .Units = New ObservableCollection(Of MillitaryUnit)((_ 
    From curLoc In curLocs1 _ 
    Where curLoc.location = SchemeLoc.Location.ID _ 
    From curName In curNames1 _ 
    Where curName.organization_id = curLoc.organization_id _ 
    And (options.UnitSizes.Count = 0 Or _ 
     options.UnitSizes.Contains(curName.UnitSize)) _ 
    And (options.UnitTypes.Count = 0 Or _ 
    options.UnitTypes.Contains(curName.UnitType)) _ 
    From curEDate In curStatuses1 _ 
    Where curEDate.organization_id = curLoc.organization_id _ 
    And (options.Statuses.Count = 0 Or _ 
    options.Statuses.Contains(curEDate.status)) _ 
    From curCmd In curCommand1 _ 
    Where curCmd.organization_id = curLoc.organization_id _ 
    And (options.Commands.Count = 0 Or _ 
    options.Commands.Contains(curCmd.service_assigned)) _ 
    From curCompo In curComponent1 _ 
    Where curCompo.organization_id = curLoc.organization_id _ 
    And (options.Components.Count = 0 Or _ 
    options.Components.Contains(curCompo.compo)) _ 
    From curTable In curLoc.Organization.organization_tables _ 
    Where curTable.organization_id = curLoc.organization_id _ 
    And (options.Tables.Count = 0 Or _ 
    (options.Tables.Contains(curTable.table_id) Or _ 
    curTable.Tables.Any(Function(a) (options.Tables.Contains(a.parent_id))))) _ 
     Select New MillitaryUnit With { _ 
     .ID = curLoc.organization_id, _ 
     .Name = curName.name, _ 
     .IconPath = curName.icon, _ 
     .ConversionStatus = curEDate.Status1.status, _ 
     .ServiceCommand = curCmd.Service_Assigneds.service_assigned, _ 
     .Component = curCompo.Components.compo}).Distinct().ToList())}).ToList()) 

UPDATE (3/3/2009 10:58 утра): мне удалось получить данные обратно в одном запросе с помощью запроса ниже, но это плоский таблица результатов. Как я могу сформировать это, чтобы материал организации становился иерархичным в каждом месте? Я считаю, что хочу использовать что-то вроде «Group Join», но я не знаком с тем, как это работает. Информация о местоположении - это все до столбца «OrgID». Мне нужно сформировать эти данные в коллекции локаций, каждая из которых имеет свойство «Единицы», которое представляет собой набор организаций, находящихся в этом месте. Любые указания?

Dim locationsquery = (From map In dc.MapBackgrounds Where map.MapID = 1 Let Locs = map.Schemes.SchemeLocations _ 
        From SchemeLoc In Locs Join curLoc In curLocs1 On SchemeLoc.LocID Equals curLoc.location _ 
        Join curName In curNames1 On curLoc.organization_id Equals curName.organization_id _ 
        Join curStatus In curStatuses1 On curLoc.organization_id Equals curStatus.organization_id _ 
        Join curCommand In curCommand1 On curLoc.organization_id Equals curCommand.organization_id _ 
        Join curComponent In curComponent1 On curLoc.organization_id Equals curComponent.organization_id _ 
        Select New With {.LocationID = SchemeLoc.LocID, .X = SchemeLoc.X, .Y = SchemeLoc.Y, _ 
             .LocationName = SchemeLoc.Location.Location, _ 
             .CountryID = SchemeLoc.Location.Countries.id, .CountryName = SchemeLoc.Location.Countries.country, _ 
             .StateID = SchemeLoc.Location.State, .StateName = SchemeLoc.Location.States.state, .StateAbbrev = SchemeLoc.Location.States.state, _ 
             .OrgID = curLoc.organization_id, _ 
             .OrgName = curName.name, _ 
             .OrgLocID = curLoc.location, _ 
             .IconPath = curName.icon, _ 
             .ConversionStatus = curStatus.status1.status, _ 
             .CurCmd = curCommand.service_assigneds.service_assigned, _ 
             .CurCompo = curComponent.components.compo}) 

ответ

0

Так я попал переделку вещи и придумал следующее решение, которое только запрашивает базу данных в два раза и гораздо быстрее:

Dim locationsOnly = (From map In dc.MapBackgrounds Where map.MapID = 1 Let Locs = map.Schemes.SchemeLocations _ 
            From SchemeLoc In Locs _ 
            Where (options.Locations.Count = 0 Or options.Locations.Contains(SchemeLoc.LocID)) _ 
            Select New With {.LocationID = SchemeLoc.LocID, .X = SchemeLoc.X, .Y = SchemeLoc.Y, _ 
             .LocationName = SchemeLoc.Location.Location, _ 
             .CountryID = SchemeLoc.Location.Countries.ID, .CountryName = SchemeLoc.Location.Countries.country, _ 
             .StateID = SchemeLoc.Location.State, .StateName = SchemeLoc.Location.States.state, .StateAbbrev = SchemeLoc.Location.States.state}).ToList() 


Dim orgsOnly = (From curLoc In curLocs1 _ 
        Join curName In curNames1 On curLoc.organization_id Equals curName.organization_id _ 
        Join curStatus In curStatuses1 On curLoc.organization_id Equals curStatus.organization_id _ 
        Join curCommand In curCommand1 On curLoc.organization_id Equals curCommand.organization_id _ 
        Join curComponent In curComponent1 On curLoc.organization_id Equals curComponent.organization_id _ 
        Join curTable In dc.organization_tables On curLoc.organization_id Equals curTable.organization_id _ 
        Where (options.UnitSizes.Count = 0 Or options.UnitSizes.Contains(curName.UnitSize)) _ 
         And (options.UnitTypes.Count = 0 Or options.UnitTypes.Contains(curName.UnitType)) _ 
         And (options.Statuses.Count = 0 Or options.Statuses.Contains(curStatus.status)) _ 
         And (options.Commands.Count = 0 Or options.Commands.Contains(curCommand.service_assigned)) _ 
         And (options.Components.Count = 0 Or options.Components.Contains(curComponent.compo)) _ 
         And (options.Tables.Count = 0 Or (options.Tables.Contains(curTable.table_id) Or curTable.Tables.Any(Function(a) (options.Tables.Contains(a.parent_id))))) _ 
        Select New With {.OrgLocID = curLoc.location, _ 
         .MilUnit = New MillitaryUnit With { _ 
         .ID = curLoc.organization_id, _ 
         .Name = curName.name, _ 
         .IconPath = curName.icon, _ 
         .ConversionStatus = curStatus.Status1.status, _ 
         .ServiceCommand = curCommand.Service_Assigneds.service_assigned, _ 
         .Component = curComponent.Components.compo}}).Distinct().ToList() 


ss.Locations = New System.Collections.ObjectModel.ObservableCollection(Of Location)((From loc In locationsOnly _ 
        Group Join org In orgsOnly On loc.LocationID Equals org.OrgLocID Into Orgs = Group _ 
        Select New Location With { _ 
         .ID = loc.LocationID, _ 
         .Name = loc.LocationName, _ 
         .X = loc.X, _ 
         .Y = loc.Y, _ 
         .Country = New Country With {.ID = loc.CountryID, .Name = loc.CountryName}, _ 
         .State = New USState With {.ID = loc.StateID, .Name = loc.StateName, .Abbreviation = loc.StateAbbrev}, _ 
         .Units = New System.Collections.ObjectModel.ObservableCollection(Of MillitaryUnit)((From curOrg In Orgs _ 
          Select curOrg.MilUnit).ToList())}).ToList()) 

Спасибо за вашу помощь casperOne!

1

Вместо того, чтобы подвергать элемент в качестве List<T>, изменить тип свойства к IEnumerable<T> или IQueryable<T>. Затем вы можете удалить вызовы в ToList, и ваш запрос должен быть выполненным полностью на сервере за один снимок.

Кроме того, этот тип кода, где LINQ to SQL начинает разрушаться, ИМО. Я думаю, что если у вас есть хранимая процедура, которая даст вам желаемые результаты, то вы должны использовать это, и просто LINQ to SQL обрабатывает отображение возвращаемых данных на ваши объекты.

+0

Мне удалось вернуть все это в одном запросе. Не могли бы вы посмотреть мой отредактированный пост, чтобы увидеть, где я застрял в одном запросе? Благодаря! – Tom

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