chr*_*ark 5 c# entity-framework-core asp.net-core
假设您有两个实体,但没有“关系”实体,您将如何删除关系?
假设以下实体...
模型类:
public class DisplayGroup
{
[Key]
public int GroupId { get; set; }
public string Description { get; set; }
public string Name { get; set; }
public ICollection<LookUpGroupItem> LookUpGroupItems { get; set; }
}
public class DisplayItem
{
[Key]
public int ItemId { get; set; }
public string Description { get; set; }
public string FileType { get; set; }
public string FileName { get; set; }
public ICollection<LookUpGroupItem> LookUpGroupItems { get; set; }
}
public class LookUpGroupItem
{
public int ItemId { get; set; }
public DisplayItem DisplayItem { get; set; }
public int GroupId { get; set; }
public DisplayGroup DisplayGroup { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这是删除关系的代码。注意:我不想删除这些实体,它们只是不再共享关系。
public void RemoveLink(DisplayGroup g, DisplayItem d)
{
_dataContext.Remove(g.LookUpGroupItems.Single(x => x.ItemId == d.ItemId));
}
Run Code Online (Sandbox Code Playgroud)
上面的方法会报错:
发生 System.ArgumentNullException
Message=Value 不能为 null。
看起来情况确实如此,因为LookUpGroupItems
is null,但这些是从数据库调用的。我同意,每当我从数据库中获取时,我不想加载所有实体关系对象,但是,最有效的方法是什么?
附加注意:这个问题与参数空异常无关。它明确说明了如何删除 Entity Framework Core 中的关系。
以下不是最有效的方法,但却是最可靠的方法:
public void RemoveLink(DisplayGroup g, DisplayItem d)
{
var link = _dataContext.Find<LookUpGroupItem>(g.GroupId, d.ItemId); // or (d.ItemId, g.GroupId) depending of how the composite PK is defined
if (link != null)
_dataContext.Remove(link);
}
Run Code Online (Sandbox Code Playgroud)
它简单明了。Find
方法用于在本地缓存中定位实体或从数据库加载它。如果找到,该Remove
方法用于将其标记为删除(这将在您调用时应用SaveChanges
)。
它不是最有效的,因为当实体不包含在本地缓存中时会进行数据库往返。
最有效的是使用“存根”实体(仅填充 FK 属性):
var link = new LookUpGroupItem { GroupId = g.GroupId, ItemId = d.ItemId };
_dataContext.Remove(link);
Run Code Online (Sandbox Code Playgroud)
这只会在调用DELETE
时发出 SQL 命令。ApplyChanges
但它有以下缺点:
(1) 如果_dataContext
已经包含(正在跟踪)LookUpGroupItem
具有相同 PK 的实体,则Remove
调用将抛出InvalidOperationException
类似“无法跟踪实体类型 'LookUpGroupItem' 的实例,因为另一个实例具有键值 'GroupId:1, ItemId: 1' 已被跟踪。附加现有实体时,请确保仅附加一个具有给定键值的实体实例。”
(2) 如果数据库表不包含具有指定复合PK的记录,则会SaveChanges
抛出“数据库操作预计影响 1 行,但实际影响 0 行。数据可能已被修改或删除,因为实体已加载。有关理解和处理乐观并发异常的信息,请参阅http://go.microsoft.com/fwlink/?LinkId=527962 。 ”(这种行为实际上被包括我在内的许多人认为是一个错误,但事实就是如此是)。DbUpdateConcurrencyException
Shorty,只有当您仅针对该操作使用短期新建DbContext
并且您绝对确定数据库中存在具有此类 PK 的记录时,您才能使用优化方法。在所有其他情况下(一般情况下),您应该使用第一种方法。
归档时间: |
|
查看次数: |
7087 次 |
最近记录: |