EF6 - 代码优先 - 如何正确处理从 m:n 关系中删除父条目
EF6 - code-first - how to properly handle deleting a parent entry from an m:n relationship
我有两个实体 - ItemGroup
和 Item
- 以 m:n 方式 linked:
CREATE TABLE ItemGroup
(
ItemGroupId INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
ItemGroupName VARCHAR(50)
)
CREATE TABLE Item
(
ItemId INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
ItemName VARCHAR(50)
)
CREATE TABLE ItemGroup_Item
(
ItemGroupId INT NOT NULL
CONSTRAINT FK_ItemGroupItem_ItemGroup
FOREIGN KEY REFERENCES dbo.ItemGroup(ItemGroupId),
ItemId INT NOT NULL
CONSTRAINT FK_ItemGroupItem_Item
FOREIGN KEY REFERENCES dbo.Item(ItemId),
CONSTRAINT PK_Itemgroup_Item
PRIMARY KEY CLUSTERED(ItemGroupId, ItemId)
)
因此,在我的 SQL 服务器数据库中,我有一个 "link" table 通过包含它们各自的主键来连接两个实体。
当我将其重新设计为 EF 6 模型时,我得到了这两个 classes:
[Table("Item")]
public partial class Item
{
public Item()
{
ItemGroup = new HashSet<ItemGroup>();
}
public int ItemId { get; set; }
[StringLength(50)]
public string ItemName { get; set; }
public virtual ICollection<ItemGroup> ItemGroup { get; set; }
}
[Table("ItemGroup")]
public partial class ItemGroup
{
public ItemGroup()
{
Item = new HashSet<Item>();
}
public int ItemGroupId { get; set; }
[StringLength(50)]
public string ItemGroupName { get; set; }
public virtual ICollection<Item> Item { get; set; }
}
并且 DbContext
class 包含以下流畅设置:
public partial class ItemGroupModel : DbContext
{
public ItemGroupModel() : base("name=ItemGroupConn")
{ }
public virtual DbSet<Item> Item { get; set; }
public virtual DbSet<ItemGroup> ItemGroup { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Item>()
.Property(e => e.ItemName)
.IsUnicode(false);
modelBuilder.Entity<Item>()
.HasMany(e => e.ItemGroup)
.WithMany(e => e.Item)
.Map(m => m.ToTable("ItemGroup_Item").MapLeftKey("ItemId").MapRightKey("ItemGroupId"));
modelBuilder.Entity<ItemGroup>()
.Property(e => e.ItemGroupName)
.IsUnicode(false);
}
}
当我试图删除 ItemGroup
:
时,我的麻烦就开始了
using(ItemGroupModel ctx = new ItemGroupModel())
{
ItemGroup grp = ctx.ItemGroup.FirstOrDefault();
ctx.ItemGroup.Remove(grp);
ctx.SaveChanges();
}
在这种情况下,我想让 EF 执行的操作是删除 "link" table 中的所有条目(在 EF 中未建模为单独的实体),然后删除ItemGroup
本身的条目。 Item
中的条目不得 被触摸!
问题是:由于此 link table 不是我的 EF 模型中的实际实体,我如何确保这些 link 条目实际上会被删除,但不会他们 link 的 Item
?所以我无法真正处理手动删除 "child" 条目 - 没有我可以访问的子条目....
我怎样才能很好地处理这个问题?有时它似乎有效 - 其他时候我得到一个异常,说 DELETE
语句与 ItemGroup_Item
中仍然存在的条目冲突....
如果有人也遇到了这个问题 - 这是解决方案:我需要在保存之前调用 ItemGroup
对象的导航 属性 上的 .Clear()
方法。 "disconnects" 任何 Item
的这个 ItemGroup
被链接到,实际上并没有删除底层 Item
对象本身 - 只是结点 table 中的条目消失了:
using(ItemGroupModel ctx = new ItemGroupModel())
{
ItemGroup grp = ctx.ItemGroup.FirstOrDefault();
// call Item.Clear() to remove any entries in the navigation
// property which translates into any entries in the junction table
// in the underlying database
grp.Item.Clear();
ctx.ItemGroup.Remove(grp);
ctx.SaveChanges();
}
我有两个实体 - ItemGroup
和 Item
- 以 m:n 方式 linked:
CREATE TABLE ItemGroup
(
ItemGroupId INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
ItemGroupName VARCHAR(50)
)
CREATE TABLE Item
(
ItemId INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
ItemName VARCHAR(50)
)
CREATE TABLE ItemGroup_Item
(
ItemGroupId INT NOT NULL
CONSTRAINT FK_ItemGroupItem_ItemGroup
FOREIGN KEY REFERENCES dbo.ItemGroup(ItemGroupId),
ItemId INT NOT NULL
CONSTRAINT FK_ItemGroupItem_Item
FOREIGN KEY REFERENCES dbo.Item(ItemId),
CONSTRAINT PK_Itemgroup_Item
PRIMARY KEY CLUSTERED(ItemGroupId, ItemId)
)
因此,在我的 SQL 服务器数据库中,我有一个 "link" table 通过包含它们各自的主键来连接两个实体。
当我将其重新设计为 EF 6 模型时,我得到了这两个 classes:
[Table("Item")]
public partial class Item
{
public Item()
{
ItemGroup = new HashSet<ItemGroup>();
}
public int ItemId { get; set; }
[StringLength(50)]
public string ItemName { get; set; }
public virtual ICollection<ItemGroup> ItemGroup { get; set; }
}
[Table("ItemGroup")]
public partial class ItemGroup
{
public ItemGroup()
{
Item = new HashSet<Item>();
}
public int ItemGroupId { get; set; }
[StringLength(50)]
public string ItemGroupName { get; set; }
public virtual ICollection<Item> Item { get; set; }
}
并且 DbContext
class 包含以下流畅设置:
public partial class ItemGroupModel : DbContext
{
public ItemGroupModel() : base("name=ItemGroupConn")
{ }
public virtual DbSet<Item> Item { get; set; }
public virtual DbSet<ItemGroup> ItemGroup { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Item>()
.Property(e => e.ItemName)
.IsUnicode(false);
modelBuilder.Entity<Item>()
.HasMany(e => e.ItemGroup)
.WithMany(e => e.Item)
.Map(m => m.ToTable("ItemGroup_Item").MapLeftKey("ItemId").MapRightKey("ItemGroupId"));
modelBuilder.Entity<ItemGroup>()
.Property(e => e.ItemGroupName)
.IsUnicode(false);
}
}
当我试图删除 ItemGroup
:
using(ItemGroupModel ctx = new ItemGroupModel())
{
ItemGroup grp = ctx.ItemGroup.FirstOrDefault();
ctx.ItemGroup.Remove(grp);
ctx.SaveChanges();
}
在这种情况下,我想让 EF 执行的操作是删除 "link" table 中的所有条目(在 EF 中未建模为单独的实体),然后删除ItemGroup
本身的条目。 Item
中的条目不得 被触摸!
问题是:由于此 link table 不是我的 EF 模型中的实际实体,我如何确保这些 link 条目实际上会被删除,但不会他们 link 的 Item
?所以我无法真正处理手动删除 "child" 条目 - 没有我可以访问的子条目....
我怎样才能很好地处理这个问题?有时它似乎有效 - 其他时候我得到一个异常,说 DELETE
语句与 ItemGroup_Item
中仍然存在的条目冲突....
如果有人也遇到了这个问题 - 这是解决方案:我需要在保存之前调用 ItemGroup
对象的导航 属性 上的 .Clear()
方法。 "disconnects" 任何 Item
的这个 ItemGroup
被链接到,实际上并没有删除底层 Item
对象本身 - 只是结点 table 中的条目消失了:
using(ItemGroupModel ctx = new ItemGroupModel())
{
ItemGroup grp = ctx.ItemGroup.FirstOrDefault();
// call Item.Clear() to remove any entries in the navigation
// property which translates into any entries in the junction table
// in the underlying database
grp.Item.Clear();
ctx.ItemGroup.Remove(grp);
ctx.SaveChanges();
}