2008-09-29 13 views
1

J'ai un niveau intermédiaire contenant plusieurs objets connexes et un niveau de données qui utilise un DataSet avec plusieurs DataTables et relations.Comment câbler un niveau intermédiaire d'objets à un niveau de données constitué d'un DataSet?

Je souhaite appeler une méthode Save sur l'un de mes objets (un objet parent) et transformer ses données de variable privée en DataRow et les ajouter à un DataTable. Certaines des données de variables privées sont en fait d'autres objets (objet enfant) dont chacun a besoin d'appeler sa propre méthode Save et de conserver ses propres données de variables.

Comment "lacer" ceci ensemble? Quelles parties d'un DataSet doivent être instanciées dans le ParentObject et que doit-on transmettre à ChildObjects pour qu'elles puissent s'ajouter à l'ensemble de données?

De même, comment connecter les relations pour 2 tables?

Les exemples que j'ai vu une relation Ordre OrderDetail créer le OrderRow et le OrderDetailRow puis appelez OrderDetailRow.SetParentRow (OrderDetail)

Je ne pense pas que cela fonctionnera pour moi depuis ma commande et OrderDetail (en utilisant leurs exemples nommage) sont dans des classes séparées et les exemples ont tout cela se passe dans une grande méthode Honking.

Merci, Keith

+0

Je pense qu'il n'y a pas eu de réponses parce qu'il est difficile de dire ce que vous faites de la description. un exemple pourrait aider –

Répondre

0

Alors, ce que je suis en train de faire est en train de passer une référence au DataSet et une référence au DataRow du parent dans la méthode Save de l'objet enfant.

Voici un petit code montrant le concept de ce que je fais.

// some random save event in a gui.cs// 
public void HandleSaveButtonClick() 
{ parentObject.Save(); } 


// Save inside the parentObject.cs // 
public void Save() 
{  
    CustomDataSet dataSet = new CustomDataSet(); 

    ParentObjectTableAdapter parentTableAdapter = new ParentObjectTableAdapter(); 

    DataTable dt = dataSet.ParentTable; 
    DataRow newParentDataRow = dt.NewRow(); 
    newParentDataRow["Property1"] = "Hello"; 
    newParentDataRow["Property2"] = "World"; 
    dt.Rows.Add(newParentDataRow); 

    parentTableAdapter.Update(dataSet.ParentTable); 

    //save children 
    _child1.Save(dataSet, newParentDataRow) 


    dataSet.AcceptChanges(); 
} 

//Save inside child1.cs // 
public void Save(CustomDataSet dataSet, DataRow parentRow) 
{ 

    Child1TableAdapter childTableAdapter= new Child1TableAdapter(); 

    DataTable dt = dataSet.ChildTable; 

    DataRow dr = dt.NewRow(); 
    dr.SetParentRow(parentRow); 
    dr["CProp1"] = "Child Property 1";  
    dt.Rows.Add(dr); 

    childTableAdapter.Update(dataSet.ChildTable); 

} 

Faites-moi savoir à quoi cela ressemble. Est-ce un modèle utilisable ou est-ce que je manque quelque chose de critique?

Merci,
Keith

2

Je ne vais pas commencer un autre débat si les ensembles de données sont bons ou mauvais. Si vous continuez à les utiliser, voici quelque chose à considérer:

  • Vous devez conserver l'ensemble de données d'origine et le mettre à jour, afin d'obtenir les insertions et mises à jour correctes.
  • Vous voulez que vos parents connaissent leurs enfants, mais pas l'inverse. Bannissez le ParentTable.
  • Un Order et ses OrderDetails sont des agrégats (issus de Domain Driven Design) et doivent être considérés dans leur ensemble. Un appel à order.Save() devrait tout sauvegarder.

Eh bien, c'est la théorie. Comment peut-on faire ça? Une façon est de créer les objets suivants:

  • Commander
  • OrderDetail
  • OrderRepository
  • OrderMap

Le OrderMap vous permet de gérer l'Ordre aux relations Dataset. En interne, il pourrait utiliser un Hashtable ou un dictionnaire.

Le OrderRepository est l'endroit où vous recevez vos commandes. Le référentiel obtiendra l'ensemble de données avec toutes les relations de quelque part, construira l'ordre avec tous ses OrderDetails, et stockera la relation Order/Dataset dans la OrderMap.

La OrderMap doit être maintenue en vie tant que l'Ordre est actif. La commande contient tous les détails de la commande. Passez la commande dans le référentiel et laissez-la l'enregistrer.

Le référentiel récupère l'ensemble de données de la carte, met à jour la table Order-Order de la commande et itère tous les détails de la commande pour mettre à jour la table OrderDetail.

Récupérer et enregistrer:

var order = repository.GetOrder(id); 
repository.Save(order); 

OrderRepository.GetOrder intérieur():

var ds = db.GetOrderAndDetailsBy(id); 
var order = new Order(); 
UpdateOrder(ds, order); 
UpdateOrderDetails(ds, order); // creates and updates OrderDetail, add it to order. 
map.Register(ds, order); 

intérieur OrderRepository.Save():

var ds = map.GetDataSetFor(order); 
UpdateFromOrder(ds, order); 
foreach(var detail in order.Details) UpdateFromDetail(ds.OrderDetail, detail); 

Quelques notes finales:

  • Vous pouvez implémenter la carte en tant que singelton.
  • Laissez la carte utiliser des références faibles. Alors n'importe quel ordre devrait être garbage-recueillis quand il devrait, et la mémoire sera libérée.
  • Vous avez besoin d'un moyen d'associer un OrderDetail à sa ligne de table
  • Si vous avez la moindre possibilité de mettre à niveau vers .NET 3.5, faites-le. Linq to Sql ou Linq to Entity supprimera une partie de votre douleur.
  • Tout cela est créé à partir de rien. J'espère que ce n'est pas trop inexact.