2014-06-30 3 views
1

J'ai table_A avec les colonnes guid_A et guid_B et la table a la clé primaire (guid_A, guid_B). Je veux sélectionner toutes les paires de guid qui existent dans un IEnumerable<Tuple<Guid, Guid>> que j'ai dans mon application, mais je ne suis pas sûr de savoir comment le faire le plus efficacement. le plus naïvement je pouvais faire des appels répétés à:Sql, comment sélectionner plusieurs résultats basés sur deux colonnes dépendantes dans un seul select?

SELECT guid_A, guid_B 
FROM table_A 
WHERE guid_A = @guidA AND guid_B = @guidB 

que j'itérer de mon IEnumerable<Tuple<Guid, Guid>> régler les paramètres que leurs valeurs respectives de la Tuple mais cela pourrait signifier de nombreux appels à la DB.

Je pensais que je pourrais changer mon IEnumerable en un Dictionary<Guid, IEnumerable<Guid>> where the key Guid is guid_A and the value is an IEnumerable` de tous les guid_B qui apparaissent avec ce guid_A et utiliser à la place un select like.

SELECT guid_A, guid_B 
FROM table_A 
WHERE guid_A = @guidA AND guid_B in (...a list of guids...) 

que j'itérer sur la construction Dictionary la liste des GUIDs que je vais. De cette façon, j'ai seulement besoin de faire un appel par guid_A que j'ai dans mes clés Dictionary. Mais j'espérais qu'il y aurait une meilleure façon d'aborder cela qui m'aiderait à sélectionner toutes les paires de guid_A, guid_B d'une liste dans une seule requête SELECT? Quelles sont les tailles relatives de la liste en mémoire et de la table de base de données?

+1

Dump votre lo okup paires dans une table temporaire et utiliser un 'JOIN'. –

Répondre

1

Il semble que ce que vous cherchez est une procédure stockée qui accepte un Table-Valued Parameter.

Pour ce faire, vous devez d'abord créer un type dans votre base de données à utiliser comme type pour le paramètre à la procédure stockée:

CREATE TYPE TVP_Guids AS TABLE(
    GUID_A UNIQUEIDENTIFIER NOT NULL , 
    GUID_B UNIQUEIDENTIFIER NOT NULL 
) 
GO 

Ensuite, vous devez créer la procédure en utilisant le type et votre tableau:

CREATE PROCEDURE s_Get_GUIDs 
    @TVPGuids TVP_Guids READONLY 
AS 
    SELECT * 
    FROM table_A t INNER JOIN @TVPGuids g 
     ON t.GUID_A = g.GUID_A 
    AND t.GUID_B = t.GUID_B 
GO 

Enfin, vous devez remplir le paramètre dans votre code:

// Placeholder for the real collection 
IEnumerable<Tuple<Guid, Guid>> cGUIDs; 

// create a data table that will be used to hold your GUIDs 
var oTable = new DataTable("GUIDs"); 
oTable.Columns.Add("GUID_A", typeof(Guid)); 
oTable.Columns.Add("GUID_B", typeof(Guid)); 

// Add each of the guids from ienumerable to the datatable 
foreach (var oTuple in cGUIDs) 
{ 
    oTable.Rows.Add(oTuple.Item1, oTuple.Item2); 
} 

using (var oConnection = new SqlConnection("Server=localhost;Database=YourDatabase;Trusted_Connection=True;")) 
{ 
    oConnection.Open(); 
    using (var oCommand = new SqlCommand("s_Get_GUIDs", oConnection)) 
    { 
     oCommand.CommandType = CommandType.StoredProcedure; 
     var oParameter = oCommand.Parameters.AddWithValue("@TVPGuids", oTable); 
     // This is necessary so ado.net knows we are passing a table-valued parameter 
     oParameter.SqlDbType = SqlDbType.Structured; 

     oCommand.ExecuteReader(); 

     // ToDo: Add remaining code here 

    } 
    oConnection.Close(); 
} 
0

Si la liste en mémoire est grande et la table DB plus petite, il est possible que le chargement de la table entière en mémoire, puis en utilisant LINQ pour joindre les 2 objets serait plus efficace.

Questions connexes