EF Core 过滤掉多对多关系中的重复实体
Posted
技术标签:
【中文标题】EF Core 过滤掉多对多关系中的重复实体【英文标题】:EF Core filtering out duplicate entities in many-to-many relationship 【发布时间】:2021-06-10 02:20:10 【问题描述】:我遇到了一个问题,即实体框架核心 5 会忽略多对多关系中的重复条目。我的“设备”可以有任意数量的“传感器”(包括多个相同的传感器)。如果我尝试将 2 个相同的 Sensor 添加到设备中,EF 只会插入 1 个。如果我将 2 个相同的 Sensor 直接添加到 DeviceSensorRelation
表中,EF 只会在 Device.Sensors
列表中显示其中一个。
我运行 SQL Server Profiler 来检查正在运行的查询,它确实返回了 EF 未显示的所有条目。这是 EF Core 的限制,还是我缺少配置或其他什么? (我假设它注意到重复的 Sensor.Id 作为它的主键,只是没有意义,因为它们之间有一个表)
我的表结构如下:
CREATE TABLE [Hardware].[Device]
(
[Id] [int] IDENTITY(1,1) NOT NULL, --PK
[Name] [varchar](200) NOT NULL,
[BuildDate] [date] NOT NULL
)
CREATE TABLE [Hardware].[Sensor]
(
[Id] [int] IDENTITY(1,1) NOT NULL, --PK
[Name] [varchar](200) NOT NULL,
[Cost] [money] NOT NULL
)
CREATE TABLE [Hardware].[DeviceSensorRelation]
(
[Id] [int] IDENTITY(1,1) NOT NULL, --PK
[DeviceId] [int] NOT NULL, --FK to Device.Id table
[SensorId] [int] NOT NULL --FK to Sensor.Id table
)
这些是 EF Core 实体:
public class Device
public int Id get;
public string Name get; private set;
public DateTime BuildDate get; private set;
private List<Sensor> sensors = new List<Sensor>();
public IReadOnlyCollection<Sensor> Sensors => this.sensors;
public class Sensor
public int Id get;
public string Name get; private set;
public decimal Cost get; private set;
private List<Device> devices = new List<Device>();
public IReadOnlyCollection<Device> Devices => this.devices;
这是在设备实体配置中设置关系的代码:
builder.HasMany(x => x.Sensors)
.WithMany(x => x.Devices)
.UsingEntity(b =>
b.ToTable("DeviceSensorRelation", "Hardware");
b.Property<int>("Id").UseIdentityColumn();
b.Property<int>("DeviceId");
b.Property<int>("SensorId");
b.HasKey("Id");
)
【问题讨论】:
您的查询是什么?你有没有尝试过将列表更改为收藏? EF Core 肯定存在一些问题。请在他们的 GitHub 问题跟踪器中检查/报告它github.com/dotnet/efcore/issues @zolfaghari 使用集合而不是列表的结果相同(它正在填充但删除重复项)。查询是指 sql 还是 linq 调用? 我想知道多次添加相同的传感器 record 是否有意义。实际上,您可能没有连接两次相同的传感器object,而是连接第二个相同type 的传感器对象。如果是这样,这两个传感器对象也需要在数据库中进行区分。每个传感器对象都应该有自己的记录。如果不是,如果一个物理传感器实际上两次连接到一个设备,那么这应该是连接记录DeviceSensorRelation
的属性,类似于NumberOfConnections
。
【参考方案1】:
我认为 EF 核心行为正确,请记住 EF 核心是数据库上的抽象,即使有 2 条记录 EF 核心只考虑“关系”。 连接表中的一条记录满足了说明两个实体是否相关所需的信息,第二条没有提供有关“实体已链接?”问题的更多信息。
您想存储和检索更多信息,您想知道传感器与设备“相关”的次数。 在这种情况下,我建议使用具有有效负载关系的多对多,并在连接实体中添加一个额外的列来存储额外信息,这可以是任何东西(由您来填充此信息):在这种情况下TypeOfDevice 和 TypeOfSensor 之间存在关系的次数。我用这些名称提到了您的实体,以关注这样一个事实,即简单的多对多将更适合将具有唯一序列号(唯一)的“具体”设备链接到具有唯一序列号的“具体”传感器。
如果在获取实体后尝试删除链接,会发生什么情况会很有趣,这 2 条记录是否都被删除?但仔细想想,我认为在 deviceId 和 sensorId 列的连接表上进行 pk 是个好主意(因为多对多的性质),所以这种情况永远不会发生。
【讨论】:
以上是关于EF Core 过滤掉多对多关系中的重复实体的主要内容,如果未能解决你的问题,请参考以下文章