Как использовать SubSonic Transaction с родительскими дочерними таблицами

У меня есть 2 таблицы (для простоты многие поля удалены)

tblOrder - OrderId - OrderDate - UserId

tblOrderDetail - OrderDetailId - OrderId - ProductId - Qantity

Я продолжаю и создаю свой объект, и я хочу сохранить все в памяти за одну транзакцию, потому что, если что-то не удается в деталях заказа, я не хочу, чтобы порядок сохранялся. Я использую следующий код, но не понимаю, как правильно это сделать за одну транзакцию.

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

// Только два для тестовых целей.

Теперь я мог бы легко это сделать

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

Но это не кажется самым элегантным решением:

  1. Потому что мне нужно перебирать каждый элемент в таблицах, чтобы установить идентификатор, а затем сохранить пакет.

  2. Потому что из-за ошибки я теряю идентификатор в своей базе данных. (т.е. при первом сохранении, если произошла ошибка, OrderId = 1 теряется, а следующий OrderId будет 2)

  3. Не масштабируется для очень больших транзакций с другой подтаблицей. В этом решении я построил пример с таблицей заказов и таблицей сведений о заказах, но в моем реальном приложении есть два других уровня под OrderDetail OrderDetailCreditMember и OrderDetailCreditCompany, где при любой покупке крошечная сумма зачисляется на счет участника и компании ( несколько строк), поэтому я могу получить дерево с 1 заказом, которое имеет 2 детали заказа, и каждая деталь заказа имеет 2 кредита участника и 3 кредита компании.

Так есть ли у кого-нибудь лучший способ сделать это.


person Philippe Asselin    schedule 03.09.2009    source источник


Ответы (1)


Честно говоря, я думаю, вы преждевременно оптимизируете здесь.

  1. Потому что мне нужно перебирать каждый элемент в таблицах, чтобы установить идентификатор, а затем сохранить пакет.

Вы выполняете итерацию в памяти, у вас есть только два вызова SQL в вашей транзакции, что мне не кажется очень неэффективным.

  1. Потому что из-за ошибки я теряю идентификатор в своей базе данных. (т.е. при первом сохранении, если произошла ошибка, OrderId = 1 теряется, а следующий OrderId будет 2)

Действительно ли это проблема, как часто вы ожидаете появления ошибки? Я предполагаю, что вы проверяете свои объекты, прежде чем пытаться их сохранить, поэтому действительно должно быть очень редко, когда вы получаете ошибку (например, не можете подключиться to db), поэтому я не уверен, что это проблема. Если вы получаете много ошибок, это проблема, которую нужно исправить отдельно.

  1. Не масштабируется для очень больших транзакций с другой подтаблицей. В этом решении я построил пример с таблицей заказов и таблицей сведений о заказах, но в моем реальном приложении есть два других уровня под OrderDetail OrderDetailCreditMember и OrderDetailCreditCompany, где при любой покупке крошечная сумма зачисляется на счет участника и компании ( несколько строк), поэтому я могу получить дерево с 1 заказом, которое имеет 2 детали заказа, и каждая деталь заказа имеет 2 кредита участника и 3 кредита компании.

Да, здесь могут быть проблемы с масштабированием, но вы говорите о 1 x 2 x 2 x 3 = 12 итерациях цикла в памяти и 3 вызовах SQL. Это действительно не должно быть большой проблемой, если только это не происходит очень регулярно. Как часто вы ожидаете, что этот метод будет вызываться?

person Adam Cooper    schedule 04.09.2009