2016-02-02 4 views
0

У меня есть следующий код в контроллере. Я пытаюсь обновить базу данных, но получаю сообщение об ошибке folliwing:Entity Framework 6 несколько транзакций savechanges с внешним ограничением ключа

Оператор INSERT противоречил ограничениям FOREIGN KEY.

using (var context = new EFDbContext()) 
{ 
    using (var dbContextTransaction = context.Database.BeginTransaction()) 
    { 
     try 
     { 
      // MessageThread 
      context.MessageThreads.Add(messageThread); 
      context.SaveChanges();        

      // Message 
      context.Messages.Add(message); 
      context.SaveChanges(); 

      // Recipient 
      context.Recipients.Add(recipient); 
      context.SaveChanges(); 

      dbContextTransaction.Commit(); 
     } 
     catch //(Exception ex) 
     { 
      ModelState.AddModelError("", "Something went wrong. Please try again."); 

      return View("Message", model); 

      // dbContextTransaction.Rollback(); no need to call this manually. 
     } 
    } 
} 

Класс Message имеет следующее свойство:

[ForeignKey("MessageThread")] 
public long MessageThreadID { get; set; } // ID 
public virtual MessageThread MessageThread { get; set; } 

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

Как это сделать за один раз? Возможно, я могу временно отключить ограничение внешнего ключа?

ответ

0

Это сообщение вашего объекта содержит объект messageThread в его свойствах? Может быть, вы можете просто вставить свой объект Message, который содержит ваш объект MessageThread?

Нечто подобное:

using (var context = new EFDbContext()) 
{ 
    using (var dbContextTransaction = context.Database.BeginTransaction()) 
    { 
     try 
     { 
      message.MessageThread = messageThread; 

      // Message 
      context.Messages.Add(message); 
      context.SaveChanges(); 

      // Recipient 
      context.Recipients.Add(recipient); 
      context.SaveChanges(); 

      dbContextTransaction.Commit(); 
     } 
     catch //(Exception ex) 
     { 
      ModelState.AddModelError("", "Something went wrong. Please try again."); 

      return View("Message", model); 

      // dbContextTransaction.Rollback(); no need to call this manually. 
     } 
    } 
} 
+0

Это не сработает. Во всяком случае, мне нужно общее решение, потому что свойство получателя, а именно MessageID, имеет отношение FK к сообщению, так же как MessageThreadID в сообщении имеет отношение FK к MessageThread. Это нужно сделать в одной партии. – nmit026

0

Это кажется 1: п отношения Messge к MessageThread.
Таким образом, вы должны иметь коллекцию MessageThread на Message, например

public virtual List<MessageThread> MessageThreads {get;set;} 

Если вы хотите добавить MessageThread к Message в той же транзакции, вы должны добавить его в этот список.

Если у вас есть автоматическое отслеживание изменений (которое по умолчанию), EntityFramework автоматически замечает, что объект был добавлен в Message и помещает его в текущий контекст.
Поэтому, когда вы вызываете SaveChanges, обе они должны быть сохранены в одной транзакции.

0

Я создавал объекты, которые будут сохранены вне сферы действия транзакции. Поэтому перед транзакционным блоком я создал три объекта подряд. Например:

MessageThread messageThread = new MessageThread(); 
Message message = new Message 
{ 
    Subject = model.Subject, 
    MessageText = model.MessageText, 
    DateSent = DateTime.UtcNow, 
    SenderID = sender.Id, 
    MessageThreadID = messageThread.MessageThreadID 
}; 
etc. 

Неудивительно, что это не сработало. Я идиот. Это была ошибка рефакторинга. Это работает:

using (var context = new EFDbContext()) 
{ 
    using (var dbContextTransaction = context.Database.BeginTransaction()) 
    { 
     try 
     { 
      // MessageThread 
      MessageThread messageThread = new MessageThread(); 
      context.MessageThreads.Add(messageThread); 
      context.SaveChanges(); 

      // Message 
      Message message = new Message 
      { 
       Subject = model.Subject, 
       MessageText = model.MessageText, 
       DateSent = DateTime.UtcNow, 
       SenderID = sender.Id, 
       MessageThreadID = messageThread.MessageThreadID 
      }; 
      context.Messages.Add(message); 
      context.SaveChanges(); 

      etc.