Службы данных ADO.NET в Silverlight: использование сгенерированного ключа в одной транзакции - PullRequest
0 голосов
/ 11 января 2010

У нас есть приложение Silverlight, которое использует службы данных WCF. Мы хотим добавить функциональность регистрации: когда генерируется новая строка, первичный ключ для этой новой строки также записывается в таблицу регистрации. Генерация строк и ведение журнала должны происходить в одной транзакции. Первичные ключи генерируются через базу данных (с использованием ключевого слова IDENTITY).

Это лучше всего проиллюстрировать на примере. Здесь я создаю новую строку Customer и в той же транзакции записываю первичный ключ клиента в строку AuditLog . В этом примере используется толстый клиент и Entity Framework:

    using (var ts = new TransactionScope())
    {
        AuditTestEntities entities = new AuditTestEntities();
        Customer c = new Customer();
        c.CustomerName = "Acme Pty Ltd";
        entities.AddToCustomer(c);
        Debug.Assert(c.CustomerID == 0);
        entities.SaveChanges();
        // The EntityFramework automatically updated the customer object
        // with the newly generated key
        Debug.Assert(c.CustomerID != 0);
        AuditLog al = new AuditLog();
        al.EntryDateTime = DateTime.Now;
        al.Description = string.Format("Created customer with customer id {0}", c.CustomerID);
        entities.AddToAuditLog(al);
        entities.SaveChanges();
        ts.Complete();
    }

Это тривиальная проблема при разработке толстого клиента с использованием Entity Framework.

Однако, используя службы данных Silverlight и ADO.NET:

  • SaveChanges может быть вызван только асинхронно
  • Я не уверен, что TransactionScope доступен
  • Я не уверен, что сгенерированные ключи могут быть отражены в клиенте Редактировать: Согласно Алекс Джеймс они действительно отражены в клиенте

Итак, будет ли это вообще возможно?

1 Ответ

4 голосов
/ 13 января 2010

Краткий ответ: Нет, это даже невозможно

Ладно ... так:

  1. Сгенерированные ключи отражаются в клиенте.
  2. Вы можете выполнить одну операцию SaveChanges с помощью DataServiceContext. SaveChanges ( SaveChangesOption.Batch )

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

Однако ...

Если вы измените модель, создав метод CustomerAuditLog, производный от AuditLog:

// Create and insert customer ...
// Create audit log and relate to un-insert customer
CustomerAuditLog al = new CustomerAuditLog(); 
al.EntryDateTime = DateTime.Now; 
al.Description = string.Format("Created customer with {Customer.ID}");
// assuming your entities implement INotifyPropertyChanging and you are using
// the Data Services Update to .NET 3.5 SP1 to use DataServiceCollection 
// to notify the DataServiceContext that a relationship has been formed. 
//
// If not you will manually need to tell Astoria about the relationship too.
al.Customer = c; 
entities.AddToAuditLog(al); 
entities.SaveChanges();

И наличие какой-то логики в глубине вашего базового источника данных или, возможно, даже базы данных для замены {Customer.ID} на соответствующее значение.

Возможно, вы сможете заставить его работать, потому что если две вставки происходят в одной и той же транзакции и одна (CustomerAuditLog) зависит от другой (Customer), они должны быть соответствующим образом упорядочены базовым источником данных.

Но, как вы можете видеть, этот подход довольно хакерский, вы не хотите, чтобы тип для каждого возможного контрольного сообщения был таким, как вы! И ... это может даже не сработать.

Надеюсь, это поможет

Alex

Служба обработки данных, Microsoft

...