繁体   English   中英

具有多表插入的EntityFramework事务回滚

[英]EntityFramework transaction rollback with multi table insert

问题:我需要在多表插入中获取一个标识,我需要在Entity Framework中包含它周围的事务支持。

我有两个(伪通用的)对象与对应的表,书和作者:

create table Author
(authorid int identity primary key,
authorname varchar(max)
)

create table Book
(bookid int identity primary key,
bookname varchar(max),
authorid int references Author(authorid)
)

我的问题是,当我需要用新作者插入一本新书时,我最终需要做这样的事情,如果Book插入引发异常我有一个没有Book的作者,这对我的应用程序不利。

context.Authors.Add(newauthor);
context.SaveChanges();
newbook.AuthorID = newauthor.ID //I can read this now because the SaveChanges() created the ID
context.Books.Add(newbook);
context.SaveChanges();

我浏览了这篇文章 ,基本上说不使用与EntityFramework的事务,并建议每次操作调用一次SaveChanges()并让EF自己处理事务。 我很乐意,但我需要首先从表中获取身份,如我的伪代码中所示和这个问题

问题是 - 你绝对需要插入作者的ID吗?

您可以先使用代码或使用db优先使用Entity进行开发。 如果您首先使用数据库,您将拥有带生成实体的.edmx文件,具有导航属性和集合......那么,上面的关键特征是什么,对于作者实体,您将拥有Books集合,这要归功于关系authorid int在您的表Book中引用Author(authorid) 因此,要向作者添加书籍,只需制作以下内容:

//Somewhere here author is created, add it to context.Authors
context.Authors.Add(newauthor);

//Somewhere here book is created, don't need to add it to context.Books; don't call SaveChanges either
newauthor.Books.Add(newbook);// And this is all you need; ID management will be done by Entity, automatically

context.SaveChanges(); // Only one call to save changes you will need
//Of course, all IDs of inserted entities will be available here... 

类似的结构也将首先对代码有效; 在作者实体中,您很可能会拥有public virtual ICollection<Book> Books集合。 并且将以与上述相同的方式完成书的创建。

当然,您可以使用多个context.SaveChanges()来获取新插入实体的ID - 您不应该这样做。 每个SaveChanges()只是广告到服务器的往返,并且可能最终会导致性能不佳。 如上所述,最好将ID值的管理留给Entity。

并且,完成故事。 使用上面的结构,EF会自动将所有内容包装到事务中的SaveChanges()中。 因此,如果Book插入失败, Author插入也将被撤消。

如果您真的不想在代码中使用事务,那么您可以将所有内容包装在存储过程中。 但是,仅仅因为默认隔离级别是可序列化的,所以没有理由不能更改它:

using(var scope = new TransactionScope(
        TransactionScopeOption.RequiresNew,
        new TransactionOptions() {
                IsolationLevel = IsolationLevel.ReadCommitted
            })) {
    context.Authors.Add(newauthor);
    context.SaveChanges();
    newbook.AuthorID = newauthor.ID
    context.Books.Add(newbook);
    context.SaveChanges();
    scope.Complete();
}

也就是说,根据Dmitriy的回答,你通常不需要手动执行此操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM