首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多表插入的EntityFramework事务回滚

问多表插入的EntityFramework事务回滚
EN

Stack Overflow用户
提问于 2013-11-06 22:52:25
回答 2查看 3.9K关注 0票数 3

问题:我需要在一个多表插入中获得一个标识,并且需要在实体框架.中封装事务支持。

我有两个(psuedo泛型)对象和相应的表,Book和Author:

代码语言:javascript
复制
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)
)

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

代码语言:javascript
复制
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自己处理事务。我很乐意,但我需要首先从表中获得身份,就像我的psuedo代码和这个问题中指出的那样

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-11-06 23:10:35

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

您可以使用实体进行开发,可以先使用代码,也可以使用db优先。如果您首先使用db,您将拥有具有生成实体、导航属性和集合的.edmx文件.因此,对于Author实体来说,由于关系authorid int references Author(authorid)在您的表书中有,上面关键特性的意义是什么。因此,要将书添加到作者,只需制作如下内容:

代码语言:javascript
复制
//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... 

类似的结构对于代码优先也是有效的;在Author实体中,您很可能拥有public virtual ICollection<Book> Books集合。书的创作将按照上面所述的方式进行。

当然,您可以使用多个context.SaveChanges()来获取新插入实体的ID --您不应该这样做。每个SaveChanges()只是在服务器的往返广告,很可能,你将以糟糕的性能结束。最好将ID值的管理留给实体,如上文所述。

然后,完成这个故事。有了上面的结构,EF会在事务中自动包装所有向上到-SaveChanges()。因此,如果Book插入失败,Author插入也将被撤消。

票数 5
EN

Stack Overflow用户

发布于 2013-11-06 23:17:07

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

代码语言:javascript
复制
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的回答,你通常不需要手工操作。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19824542

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档