ten*_*its 10 c# entity-framework code-first ef-code-first entity-framework-6
我有EntityFramework的条目删除问题和同一实体的多对多关系.考虑这个简单的例子:
实体:
public class UserEntity {
// ...
public virtual Collection<UserEntity> Friends { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
流畅的API配置:
modelBuilder.Entity<UserEntity>()
.HasMany(u => u.Friends)
.WithMany()
.Map(m =>
{
m.MapLeftKey("UserId");
m.MapRightKey("FriendId");
m.ToTable("FriendshipRelation");
});
Run Code Online (Sandbox Code Playgroud)
Cascade Delete在Fluent API中定义?UserEntity例如,删除a的最佳方法是什么Foo?
现在找我,我一定要Clear对Foo的Friends集合,然后我需要加载的所有其他UserEntities,其中包含Foo在Friends,然后取出Foo从每个列表,之前我删除Foo的Users.但这听起来太复杂了.
是否可以直接访问关系表,以便我可以删除这样的条目
// Dummy code
var query = dbCtx.Set("FriendshipRelation").Where(x => x.UserId == Foo.Id || x.FriendId == Foo.Id);
dbCtx.Set("FriendshipRelation").RemoveRange(query);
Run Code Online (Sandbox Code Playgroud)谢谢!
Update01:
我知道这个问题的最佳解决方案是在调用之前执行原始sql语句SaveChanges:
dbCtx.Database.ExecuteSqlCommand(
"delete from dbo.FriendshipRelation where UserId = @id or FriendId = @id",
new SqlParameter("id", Foo.Id));
Run Code Online (Sandbox Code Playgroud)
但这样做的缺点是,如果SaveChanges由于某种原因导致失败,FriendshipRelation则已经被删除而无法回滚.还是我错了?
Fab*_*Luz 12
答案很简单:
当实体框架不知道哪些属性属于该关系时,它无法定义级联删除.
此外,在许多:很多关系中,有第三个表,负责管理关系.此表必须至少有2个FK.您应该为每个FK配置级联删除,而不是为"整个表".
解决方案是创建FriendshipRelation实体.像这样:
public class UserFriendship
{
public int UserEntityId { get; set; } // the "maker" of the friendship
public int FriendEntityId { get; set; }´ // the "target" of the friendship
public UserEntity User { get; set; } // the "maker" of the friendship
public UserEntity Friend { get; set; } // the "target" of the friendship
}
Run Code Online (Sandbox Code Playgroud)
现在,你必须改变UserEntity.UserEntity它有一个集合而不是集合UserFriendship.像这样:
public class UserEntity
{
...
public virtual ICollection<UserFriendship> Friends { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我们来看看映射:
modelBuilder.Entity<UserFriendship>()
.HasKey(i => new { i.UserEntityId, i.FriendEntityId });
modelBuilder.Entity<UserFriendship>()
.HasRequired(i => i.User)
.WithMany(i => i.Friends)
.HasForeignKey(i => i.UserEntityId)
.WillCascadeOnDelete(true); //the one
modelBuilder.Entity<UserFriendship>()
.HasRequired(i => i.Friend)
.WithMany()
.HasForeignKey(i => i.FriendEntityId)
.WillCascadeOnDelete(true); //the one
Run Code Online (Sandbox Code Playgroud)
生成的迁移:
CreateTable(
"dbo.UserFriendships",
c => new
{
UserEntityId = c.Int(nullable: false),
FriendEntityId = c.Int(nullable: false),
})
.PrimaryKey(t => new { t.UserEntityId, t.FriendEntityId })
.ForeignKey("dbo.UserEntities", t => t.FriendEntityId, true)
.ForeignKey("dbo.UserEntities", t => t.UserEntityId, true)
.Index(t => t.UserEntityId)
.Index(t => t.FriendEntityId);
Run Code Online (Sandbox Code Playgroud)
要检索所有用户的朋友:
var someUser = ctx.UserEntity
.Include(i => i.Friends.Select(x=> x.Friend))
.SingleOrDefault(i => i.UserEntityId == 1);
Run Code Online (Sandbox Code Playgroud)
所有这一切都很好.但是,映射存在问题(在当前映射中也会发生).假设"我"是UserEntity:
当我检索我的Friends财产时,它返回"John","Ann",但不是"Richard".为什么?因为理查德是关系的"制造者"而不是我.该Friends属性仅限于该关系的一方.
好.我怎么解决这个问题?简单!改变你的UserEntity课程:
public class UserEntity
{
//...
//friend request that I made
public virtual ICollection<UserFriendship> FriendRequestsMade { get; set; }
//friend request that I accepted
public virtual ICollection<UserFriendship> FriendRequestsAccepted { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
更新映射:
modelBuilder.Entity<UserFriendship>()
.HasRequired(i => i.User)
.WithMany(i => i.FriendRequestsMade)
.HasForeignKey(i => i.UserEntityId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<UserFriendship>()
.HasRequired(i => i.Friend)
.WithMany(i => i.FriendRequestsAccepted)
.HasForeignKey(i => i.FriendEntityId)
.WillCascadeOnDelete(false);
Run Code Online (Sandbox Code Playgroud)
不需要迁移.
要检索所有用户的朋友:
var someUser = ctx.UserEntity
.Include(i => i.FriendRequestsMade.Select(x=> x.Friend))
.Include(i => i.FriendRequestsAccepted.Select(x => x.User))
.SingleOrDefault(i => i.UserEntityId == 1);
Run Code Online (Sandbox Code Playgroud)
是的,您必须迭代集合并删除所有子对象.请参阅此线程中的答案干净地更新实体框架中的层次结构
根据我的回答,只需创建一个UserFriendshipdbset:
public DbSet<UserFriendship> UserFriendships { get; set; }
Run Code Online (Sandbox Code Playgroud)
现在,您可以检索特定用户ID的所有朋友,只需一次删除所有朋友,然后删除该用户.
对的,这是可能的.你UserFriendship现在有一个dbset.
希望能帮助到你!
| 归档时间: |
|
| 查看次数: |
8450 次 |
| 最近记录: |