Far*_*ori 9 c# entity-framework optimistic-concurrency
我有一个拥有多对多自我关系的实体.作为一个例子考虑这个实体:
public class User
{
public int ID { get; set; }
public string UserName { get; set; }
public virtual ICollection<User> Friends { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
以下是我配置映射的方法:
HasMany(t => t.Friends).WithMany()
.Map(m => {
m.MapLeftKey("UserID");
m.MapRightKey("FriendID");
m.ToTable("UserFriends");
});
Run Code Online (Sandbox Code Playgroud)
由于此关系现在由EF管理,我实际上无法访问UserFriends DbSet我的代码并且无法处理对它的并发访问.为了使这个组合处理并发访问(添加/删除),我是否需要自己处理多对多关系,然后添加一个[Timestamp]列或者有没有办法告诉EF自己同时处理它?就像模型构建器中的配置一样.
编辑:我正在使用EF 6,目前如果实体上有并发操作(例如,尝试删除当前未在数据库上退出的朋友),我收到以下错误消息,并且DbUpdateException:
保存不公开其关系的外键属性的实体时发生错误.EntityEntries属性将返回null,因为无法将单个实体标识为异常的来源.通过在实体类型中公开外键属性,可以更轻松地在保存时处理异常.有关详细信息,请参阅InnerException.
虽然 UserFriends 表上没有 rowversion 列,但 EF 仍然能够识别出 DbContext.SaveChanges 失败的原因是多对多关系中的并发问题。在这种情况下,ef 会抛出 OptimisticConcurrencyException 异常,并且使用 DbUpdateException 进行不透明处理。使用以下代码来捕获它:
try
{
context.SaveChanges();
}
catch (DbUpdateException ex)
{
if(ex.InnerException is OptimisticConcurrencyException)
{
// If you are here then there was concurrency problem in many-to-many relationship
}
}
Run Code Online (Sandbox Code Playgroud)
您可能无法将当前的 Fluent api 配置为自动包含在 UserFriends 表 rowversion 列中,但是生成迁移后,您可以手动添加到 UserFriends CreateTable 语句 rowversion 列的定义:
CreateTable(
"dbo.UserFriends",
c => new{
RowVersion = c.Binary(nullable: false, fixedLength: true, timestamp: true, storeType: "rowversion"),
// other columns definitions
});
Run Code Online (Sandbox Code Playgroud)
但是,当多对多关系中发生并发问题时,这不会改变 DbContext 的行为。