2009-03-02 5 views
1

Je suis assez nouveau pour LINQ en général, mais j'ai réussi à comprendre les choses jusqu'à présent pour obtenir le résultat souhaité. La requête LINQ2SQL ci-dessous produit les résultats souhaités dans lesquels se trouvent des objets Location, chacun avec sa propre collection d'unités. Les déclarations de variables initiales sont effectuées pour configurer les valeurs que je dois interroger et ne doivent pas être pertinentes pour mon problème, mais sont nécessaires pour le contexte. Le problème que j'ai est qu'il y a plus de 400 emplacements, et la manière actuelle dont j'ai la requête structurée, il frappe la base de données pour chacun au lieu d'une grande requête. Cela cause des problèmes de performance, en prenant 30 secondes pour que le résultat complet revienne, ce qui est inacceptable. J'ai une requête SQL de procédure stockée qui renvoie les résultats dans seulement une seconde ou deux.Remplissage de la propriété de collection enfant avec la sous-requête LINQ

Existe-t-il un moyen de restructurer cette requête afin que je ne frappe pas la base de données pour chaque emplacement? Je suis sûr qu'il est causé par l'extra "ToList()" sur la sous-requête Units mais je ne sais pas comment former le résultat sans ToList(). Toute modification des performances serait une aide énorme. Merci pour toute aide!

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()) 

MISE À JOUR (3/3/2009 10:58): Je réussi à récupérer les données dans une requête en utilisant la requête ci-dessous, mais il est un résultat de table plat. Comment puis-je façonner cela pour que l'organisation devienne hiérarchique sous chaque emplacement? Je crois que je veux utiliser quelque chose comme "Group Join" mais je ne suis pas familier avec la façon dont cela fonctionne. L'information de localisation est tout jusqu'à la colonne "OrgID". J'ai besoin de façonner ces données dans une collection d'emplacements qui ont chacun une propriété "Unités" qui est une collection des organisations qui sont à cet endroit. Des conseils?

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}) 

Répondre

0

donc j'ai fini par refaire les choses et est venu avec la solution suivante qui porte uniquement sur la base de données deux fois et est beaucoup plus rapide:

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()) 

Merci pour votre casperOne aide!

1

au lieu d'exposer le membre comme List<T>, changer le type de propriété à un IEnumerable<T> ou un IQueryable<T>. Ensuite, vous pouvez supprimer les appels à ToList et votre requête devrait être capable d'être exécuté complètement sur le serveur en une seule fois.

En outre, ce type de code est où LINQ to SQL commence à se décomposer, IMO. Je pense que si vous avez une procédure stockée qui vous donnera les résultats souhaités, alors vous devriez utiliser cela, et juste avoir LINQ to SQL gérer le mappage des données renvoyées à vos objets.

+0

J'ai réussi à tout récupérer en une seule requête. Pouvez-vous s'il vous plaît jeter un oeil à mon post édité pour voir où je suis coincé avec la requête? Merci! – Tom

Questions connexes