我使用mehdime/DbContextScope作为documented here来为我们的产品实施批量用户刷新/导入解决方案。
在标题“仅在调用SaveChanges()时保持更改”时,Mehdi在代码示例中说明:
在业务交易完成之前,请勿调用SaveChanges() - 即没有部分或中间保存。必须调用SaveChanges() 每个商业交易一次。
如果您发现需要多次调用SaveChanges() 在商业交易中,这意味着你实际上 在单个服务中实现多个业务事务 方法
但是,我想添加一个新行,获取其生成的ID(IDENTITY列),然后将一个审核日志条目添加到引用生成的ID的数据库中。为此,我需要执行一个中间SaveChanges()
,以便EF执行INSERT并获取ID,但是我想在单个原子事务中执行此操作。
我是否遗漏了某些内容,或者在不违反Medhi规则的情况下实际可行吗?
这是我的代码示例(当前违反了规则)
/// <summary>
/// Creates a new Location
/// </summary>
/// <param name="orgID">ID of Organisation</param>
/// <param name="name">Location Name</param>
/// <returns></returns>
public IActionResult Create(int orgID, string name)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentNullException(nameof(name));
// New Location
var location = new Location {
OrganisationID = orgID,
Name = name,
Enabled = true
};
using (var dbContextScope = _dbContextScopeFactory.Create())
{
var ctx = dbContextScope.DbContexts.Get<PlatformEntities2014>();
// Duplicate name?
var existing = ctx.Locations.Where(l => l.OrganisationID == orgID && l.Name == name).FirstOrDefault();
if (existing != null)
return new ActionResult(ActionResultCode.ErrorAlreadyExists) { ReferencedObject = existing };
ctx.Locations.Add(location);
// ---POSITION A---
dbContextScope.SaveChanges(); // (Assigns location.ID)
// Log
GeneralLog log = new GeneralLog() {
DateTime = DateTime.Now,
Code = "LOC",
SubCode = "NEW",
OrganisationID = orgID,
Information = $"Location {location.ID} \"{location.Name}\" created during Bulk Refresh."
};
ctx.GeneralLogs.Add(log);
// ---POSITION B---
dbContextScope.SaveChanges();
return new ActionResult(ActionResultCode.Success) { ReferencedObject = location };
}
}
将位置A 中的第一个dbContextScope.SaveChanges();
替换为ctx.SaveChanges();
以获取ID并在 POSITION B处拨打dbContextScope.SaveChanges();
是否可以接受
感谢。
答案 0 :(得分:2)
继续解释评论中的关系。这是两个独立的商业交易。以这种方式看待它,如果它不能创建一个&#39; GeneralLog&#39;你的交易不被视为失败。因此,我会说这是两个单独的交易。记录不应该使您的业务交易失败。您可以做的是在一个事务中首先创建对象。获取ID并在单独的事务中创建日志。