2009-02-26 6 views
3

J'utilise C# et SQL Server 2005 et j'ai besoin d'une recommandation sur la façon de remplir mes objets.C# connexions multiples vs jeu de données

J'ai une collection Customers contenant une collection d'objets clients. Chaque objet client contient une collection Orders contenant une collection de commandes. J'utilise une méthode publique Fetch() sur ma collection Customers pour renseigner les clients et leurs commandes.

Vous ne pouvez avoir qu'un seul DataReader ouvert par connexion, à droite. Cela signifie donc que j'ai besoin d'une connexion pour le lecteur 'SELECT * Customers', et pendant que je parcoure le lecteur client, j'aurais besoin d'une autre connexion pour chaque 'SELECT * Orders WHERE CustomerId_fk = @Id'.

Ma question: Recommanderiez-vous que j'utilise la méthode ci-dessus ou simplement DataSets?

EDIT

j'avais 'SELECT * Clients WHERE Id = @Id' au lieu de 'SELECT * Les clients'.

Répondre

3

En fait, votre assertion ("Vous ne pouvez avoir qu'un DataReader ouvert par connexion") est incorrecte; vous pouvez enable MARS (plusieurs ensembles de résultats actifs) via un tweak à la chaîne de connexion, et le travail effectué; sauf bien sûr que vous aurez encore beaucoup d'allers-retours (n + 1).

Je ne pense pas non plus que l'alternative immédiate soit les jeux de données. Personnellement, j'utiliserais deux grilles de résultats (provenant d'une seule requête ou de deux requêtes) et les assemblerais à nouveau à l'appelant. Vous pouvez également utiliser quelque chose comme LINQ-to-SQL avec LoadWith<Customer>(c=>c.Orders); (DataLoadOptions). Même sans LoadWith, il fera automatiquement le même comportement n + 1 simplement en chargeant la collection pour chaque Customer (les propriétés de navigation sont chargées paresseusement par défaut).

2

J'utiliserais probablement un SqlDataAdapter pour interroger les deux en un seul passage dans un DataSet. Quelque chose comme ceci:

SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM CUSTOMERS WHERE CustomerId = @id; SELECT * FROM ORDERS WHERE CustomerId = @id",connection); 
adapter.Fill(dataSet); 

Ensuite, je mis en place la relation en utilisant quelque chose comme ceci:

dataSet.Relations.Add(new DataRelation("relationName", dataSet.Tables[0].Columns["CustomerId"], dataSet.Tables[1].Columns["CustomerId"]); 

De cette façon, vous ouvrez une seule connexion, vous interrogez toutes les données, puis définissez jusqu'à la relation dans la mémoire.

0

Merde! Je venais de mordre ma main et d'utiliser deux connexions. N'oubliez pas de fermer 'em et le lecteur de données bien que.

Je ne sais pas pourquoi, je ne peux pas me résoudre à utiliser DataSet n'importe où ...!

1

Je vais juste développer la réponse de Marc. Un DataReader peut lire plusieurs ensembles de résultats en même temps. Donc, vous pouvez faire ce qui suit:

string sql = "SELECT * FROM Customers; SELECT * FROM Orders;"; 
using (SqlCommand cmd = new SqlCommand(sql, connection)) 
using (SqlDataReader rd = cmd.ExecuteReader()) 
{ 

    while (rd.Read()) 
    { 
    // Read customers 
    } 

    if (rd.NextResult()) // Change result set to Orders 
    { 
    while(rd.Read()) 
    { 
     // Read orders 
    } 

    } 
} 

Bien sûr, vous ne récupérerez que les données nécessaires, mais vous obtenez le point. Cela vous permet d'obtenir les deux ensembles de résultats en utilisant une commande.

+0

Ceci couvre un de mes points (plusieurs grilles d'une commande); notez que le point MARS est une question distincte ;-p –

+0

MARS peut être vraiment utile, mais ici je ne pense pas que ce soit nécessaire –

Questions connexes