Я использую Entity Framework для моделирования простых родительских и дочерних отношений между документом и его страницами. Следующий код должен (в этом порядке):
- сделать несколько обновлений свойств документа
- удалить любую из существующих страниц документа
- вставить новый список страниц, переданных в метод.
Новые страницы имеют те же ключи, что и удаленные страницы, поскольку существует индекс, который состоит из номера документа, а затем номера страницы (1..n).
Этот код работает. Однако, когда я удаляю первый вызов SaveChanges, он завершается неудачно с:
System.Data.SqlClient.SqlException: Cannot insert duplicate key row in object
'dbo.DocPages' with unique index 'IX_DocPages'.
Вот рабочий код с двумя вызовами SaveChanges:
Document doc = _docRepository.GetDocumentByRepositoryDocKey(repository.Repository_ID, repositoryDocKey);
if (doc == null) {
doc = new Document();
_docRepository.Add(doc);
}
_fieldSetter.SetDocumentFields(doc, fieldValues);
List<DocPage> pagesToDelete = (from p in doc.DocPages
select p).ToList();
foreach (DocPage page in pagesToDelete) {
_docRepository.DeletePage(page);
}
_docRepository.GetUnitOfWork().SaveChanges(); //IF WE TAKE THIS OUT IT FAILS
int pageNo = 0;
foreach (ConcordanceDatabase.PageFile pageFile in pageList) {
++pageNo;
DocPage newPage = new DocPage();
newPage.PageNumber = pageNo;
newPage.ImageRelativePath = pageFile.Filespec;
doc.DocPages.Add(newPage);
}
_docRepository.GetUnitOfWork().SaveChanges(); //WHY CAN'T THIS BE THE ONLY CALL TO SaveChanges
Если я оставлю код как написано, EF создаст две транзакции - по одной для каждого вызова SaveChanges. Первый обновляет документ и удаляет все существующие страницы. Вторая транзакция вставляет новые страницы. Я изучил трассировку SQL, и вот что я вижу.
Однако , если я удаляю первый вызов SaveChanges (потому что я хотел бы, чтобы все это выполнялось в одной транзакции), EF таинственным образом вообще не удаляет, а генерирует только вставки ?? - которые приводят к ошибке дубликата ключа. Я не думаю, что ожидание вызова SaveChanges должно иметь значение здесь?
Между прочим, при вызове _docRepository.DeletePage (page) выполняется objectContext.DeleteObject (page). Кто-нибудь может объяснить это поведение? Спасибо.