2009-09-03 4 views
0

J'ai 2 tables (Pour simplifier beaucoup domaine où enlevé)Comment utiliser la transaction subsonique avec les parents Tables d'enfants

tblOrder - OrderId - OrderDate - UserId

tblOrderDetail - OrderDetailId - OrderId - ProductId - Qantity

Je vais de l'avant et crée mon objet et je veux tout garder en mémoire en une seule fois car si quelque chose échoue dans les détails de la commande, je ne veux pas que la commande soit enregistrée. J'utilise le code suivant, mais je ne comprends pas comment le faire correctement en une seule transaction.

Order newOrder = new Order(); 
OrderDetailCollection newOrderDetails = new OrderDetailCollection(); 
OrderDetail newOrderDetail; 

newOrder.OrderDate = DateTime.Now(); 
newOrder.UserId = 1; 

newOrderDetail = new OrderDetail(); 
// newOrderDetail.OrderId = newOrder.OrderId; // Can't do that yet, newOrder is not saved and OrderId is Null. 
newOrderDetail.ProductId = 1; 
newOrderDetail.Quantity = 25; 

newOrderDetails.Add(newOrderDetail); 

newOrderDetail = new OrderDetail(); 
// newOrderDetail.OrderId = newOrder.OrderId; // Can't do that yet, newOrder is not saved and OrderId is Null. 
newOrderDetail.ProductId = 1; 
newOrderDetail.Quantity = 25; 

newOrderDetails.Add(newOrderDetail); 

// Seulement deux à des fins de test.

Maintenant, je pourrais le faire facilement

using (System.Transactions.TransactionScope ts = new TransactionScope()) {  
    using (SharedDbConnectionScope scs = new SharedDbConnectionScope()) { 
     try { 
     newOrder.Save(); 

     foreach(OrderDetail anOrderDetail in newOrderDetails) { 
      anOrderDetail.OrderId = newOrder.OrderId; 
     } 

     newOrderDetails.BatchSave(); 

     ts.Complete(); 
     }   
     catch (Exception ex) { 
     //Do stuff with exception or throw it to caller 
     } 
    } 
} 

Mais cela ne semble pas la solution la plus élégante:

  1. Parce que je dois parcourir chaque élément dans les tableaux pour définir l'ID et puis sauvegardez le lot. Parce que sur erreur, je perds un ID dans ma base de données. (c'est-à-dire lors de la première sauvegarde si une erreur est survenue, OrderId = 1 est perdue et OrderId suivante sera 2)

  2. Non extensible pour une très grande transaction avec une autre sous-table. Dans cette solution, j'ai construit l'exemple avec une table Order et une table Order Order mais dans ma vraie application, il y a deux autres niveaux sous OrderDetail OrderDetailCreditMember et OrderDetailCreditCompany où sur tout achat, un minuscule montant est crédité au membre et à l'entreprise (plusieurs rangs) donc je peux finir par avoir un arbre avec 1 commande qui a 2 détails de la commande et chaque détail de la commande a 2 crédits de membre et 3 crédits de compagnie.

Alors quelqu'un a-t-il une meilleure façon de le faire.

Répondre

2

Pour être honnête, je pense que vous pouvez optimiser prématurément ici. Parce que je dois parcourir chaque élément dans les tables pour définir l'ID, puis enregistrer le lot. Vous itérez en mémoire que vous avez seulement deux appels SQL dans votre transaction, ne me semble pas massivement inefficace. Parce que sur erreur, je perds un ID dans ma base de données. (Par exemple sur d'abord enregistrer si une erreur est survenue, OrderId = 1 est perdu et suivant OrderId sera 2)

Est-ce vraiment un problème, comment voulez-vous attendre souvent une erreur de se produire, je suppose que vous » re valider vos objets avant d'essayer de les sauvegarder, donc il devrait être très rare que vous obteniez une erreur (par exemple, vous ne pouvez pas vous connecter à DB), donc je ne suis pas convaincu que c'est un problème. Si vous rencontrez beaucoup d'erreurs, c'est un problème qui doit être résolu séparément.

  1. Non modulable pour une transaction très importante avec une autre sous-table. Dans cette solution, j'ai construit l'exemple avec une table Order et une table Order Order mais dans ma vraie application, il y a deux autres niveaux sous OrderDetail OrderDetailCreditMember et OrderDetailCreditCompany où sur tout achat, un minuscule montant est crédité au membre et à l'entreprise (plusieurs rangs) donc je peux finir par avoir un arbre avec 1 commande qui a 2 détails de la commande et chaque détail de la commande a 2 crédits de membre et 3 crédits de compagnie. Oui, il pourrait y avoir des problèmes de mise à l'échelle ici, mais vous parlez de 1 x 2 x 2 x 3 = 12 itérations d'une boucle en mémoire ici et 3 appels SQL. Cela ne devrait vraiment pas poser trop de problèmes à moins que cela ne se produise très régulièrement. À quelle fréquence attendez-vous que cette méthode soit appelée?

Questions connexes