我得到了一个数据库(因此我不能更改它),该数据库包含使用version数字列进行版本控制的实体.

实体为住所地址.这些实体中的每个实体都有一个由id和版本组成的复合主键.

可以有多个住所s,住所引用地址.地址可以由不同的住所s引用.因此,我们在住所s之间存在一对多关系,在住所地址之间存在多对一关系.

每个实体只使用id引用另一个实体,因此每个实体的版本都是独立的.

让我给你举一个表格的例子:

|id|version|etc.
|1 |1      |...
|1 |2      |...

住所

|id|version|person_id|address_id|etc...
|2 |1      |1        |3         |...
|2 |2      |1        |3         |...
|3 |1      |1        |4         |...

地址

|id|version|etc...
|3 |1      |...
|3 |2      |...
|4 |1      |...

正如您可以看到的,每个实体仅使用id相互引用,并且同一实体可以有多个版本,因此您可以多次拥有相同的id.

我希望我的模型实体看起来类似于:

public class 人 {
  public long Id {get; set;}
  public long Version {get; set;}
  public List<住所> 住所s {get; set;}
}

public class 住所 {
  public long Id {get; set;}
  public long Version {get; set;}
  public long 地址Id {get; set;}
  public List<地址> 地址Versions {get; set;}
}

public class 地址 {
  public long Id {get; set;}
  public long Version {get; set;}
}

配置一个人与其住所之间的关系很简单:

modelBuilder.Entity<人>(entity => {
  //...
  entity.HasMany(p => p.住所s)
    .WithOne()
    .HasForeignKey(d => d.人Id)
    .HasPrincipalKey(p => p.Id);
});

Now comes the part that I have no clue how to configure: the relationship between a 住所 and its 地址 versions. In theory this relation should be a many-to-one because one 地址 is used by multiple 住所s.

I want to have ALL the 地址 versions on the 住所 so I've declared the property public List<地址> 地址Versions, but now I have to configure the navigation property.

如果我try 将关系配置为:

modelBuilder.Entity<住所>(entity => {
  //...
  entity.HasMany(p => p.地址Versions)
    .WithMany());
});

这将无法编译,因为多对多关系需要两端都有导航属性.

如果我try 使用一对多配置对关系进行建模:

modelBuilder.Entity<住所>(entity => {
  //...
  entity.HasMany(p => p.地址Versions)
    .WithOne()
    .HasPrincipalKey(p => p.地址Id);
});

It will not work because I don't have a foreign key on 地址 that refers to 住所 given that an 地址 is used by multiple 住所s.

如果我用另一种方式处理这段关系:

modelBuilder.Entity<住所>(entity => {
  //...
  entity.HasOne(p => p.地址)
    .WithMany()
    .HasForeignKey(p => p.地址Id)
    .HasPrincipalKey(d => d.Id);
});

Despite this works I get just one of the many possibile versions of an 地址, losing information.

How can I model such relations like between 地址 and 住所 and making available on the principal entity all the versions of the related entity ?

编辑:

对数据的一些澄清:

每个实体都有一个复合主键,定义如下:

PRIMARY KEY (id, version);

此复合主键唯一标识特定记录和版本.

每个实体使用如下定义的外键引用另一个实体:

CREATE TABLE 住所(
  --etc.
  CONSTRAINT fk_address FOREIGN KEY (address_id) REFERENCES address (id)
);

正如您所看到的,外键只引用了主键的一部分.

In the example table that I provided above I expect that when I select 人 with id 1 and version 2 I get 3 domiciles back (id 2 and the two versions 1 and 2 and id 3 with just one version).
Then, for every version of domicile with id 2, I expect 2 addresses (id 3 with version 1 and 2) and for the single version of domicile with id 3 I exepect 1 address (id 4 with version 1)

In code we could write my expectation for 住所 with id 2 as:

Assert.That(domicile.地址es.Count, Is.EqualTo(3));

Assert.That(domicile.地址es[0].Id, Is.EqualTo(3));
Assert.That(domicile.地址es[0].Version, Is.EqualTo(1));

Assert.That(domicile.地址es[1].Id, Is.EqualTo(3)); //Same address id as before...
Assert.That(domicile.地址es[0].Version, Is.EqualTo(2)); //...but different version

问题似乎是,外键不引用唯一行,因为它只使用了part个主键,因此这种关系不能用实体框架核心建模(也许?).

希望这能更好地阐明我必须处理什么以及我想要得到什么.

推荐答案

简而言之,你想要的东西不能用内置功能来完成.也许第三方扩展/工具可以提供帮助.

Id对于您的三个实体中的任何一个都不是唯一的,因此您不能仅使用Id属性作为主键(因为主键必须唯一标识相关记录)来在它们之间具有多对一或一对多关系.

选项:

  1. 手动连接这些实体并投影结果
  2. 创建DB视图(如果允许)以提供EF可用于多对多关系的连接实体.

Csharp相关问答推荐

在Dapper中使用IasyncEum重写GetAsyncEum方法

处理. netstandard2.0项目中HttpClient.SslProtocol的PlatformNotSupportedException问题""

解析需要HttpClient和字符串的服务

如何告诉自己创建的NuGet包在应用程序中发生了变化?

如果属性名为xyz,我需要使用System.Text.Json修改字符串类型的值""<>

mocking对象的引发事件并作为用于调用方法的参数对象传递到那里

在实体框架中处理通用实体&S变更跟踪器

为具有实体框架后端的Reaction项目 Select 正确的Visual Studio模板

Automapper 12.x将GUID映射到字符串

C#普罗米修斯指标

为什么@rendermode Interactive Auto不能在.NET 8.0 Blazor中运行?

.NET:从XPath定位原始XML文档中的 node

异步任务调用程序集

如何在C#中正确类型化带有泛型的嵌套类

毛伊岛.NET 8图片不再适合按钮

如何为控制器PUT操作绑定对象数组

使用SQL Server 2022+时,我是否必须将代码从SqlConnection类对象中迁移出来?

ASP.NET核心MVC|如何在控制器方法之间传递值

测试单个对象是否与Func<;T,bool>;匹配

Avalonia MVVM数据模板