实体框架以正确的方式插入 3 个表并在异常时回滚
-
20-12-2019 - |
题
我有一个非常简单的问题,我正在绞尽脑汁思考如何才能完全正确地做到这一点。现在使用实体框架并尝试存储库模式我有3张桌子:
Story id PRIMARY KEY IDENTITY
Album id PRIMARY KEY IDENTITY
Photo id PRIMARY KEY IDENTITY
我想插入一个像这样的新故事:
_db.Repository.Insert(oneStory);
Save(); // Save will save it to table story
oneStory.id; // return id of last added row.
然后使用最近添加的故事的 id 我想像这样保存专辑
oneAlbum.fk_storyid=oneStory.id
_db.Repository.Insert(oneAlbum);
Save(); // Save will save it to table album
oneAlbum.id; // return id of last added row.
然后使用最近添加的相册的 id 我想像这样保存照片
onePhoto.fk_albumid=oneAlbum.id
_db.Repository.Insert(onePhoto);
Save(); // Save will save it to table photo
onePhoto.id; // return id of last added row.
这是问题所在
- 如果保存相册或照片时发生异常,故事已添加,也许相册也已添加,如何回滚并删除该故事或更改?
- -大问题是,我们可以不使用 Save() 并仅使用 insert 来获取最近添加的行的 id 吗?这样我就可以完成所有插入,并不断获取 id,然后像工作单元一样最后保存。
那么有人可以指导我如何完美地完成这将节省时间和更少的代码并且还有良好的结构。谢谢。
解决方案
在实体框架中 DbContext
本身既是一个 存储库 和一个 工作单元.
如果您想在此基础上构建额外的存储库,您应该注入 DbContext
以便所有操作都使用相同的 DbContext
你只需要打电话 SaveChanges
一次。
在这种情况下,您应该使用导航属性将对象相互链接而不是外键 - 因为您还没有任何键值。EF 将自动按正确的顺序插入内容并将值分配给外键。
如果这不是一个选项,您可以使用 TransactionScope
将所有内容包装在一笔交易中:
using(var tx = new TransactionScope())
{
_db.Repository.Insert(oneStory);
Save(); // Save will save it to table story
oneStory.id; // return id of last added row.
_db.Repository.Insert(oneStory);
Save(); // Save will save it to table story
oneStory.id; // return id of last added row.
onePhoto.fk_albumid=oneAlbum.id
_db.Repository.Insert(onePhoto);
Save(); // Save will save it to table photo
onePhoto.id; // return id of last added row.
tx.Complete();
}
不隶属于 StackOverflow