与具有多行的 fk 建立一对多关系

Setup one to many relation with fk having multiple rows

我在设置与 EF Core 的一对多关系时遇到问题。
我有两个 tables addressaddress_country。有模式:

如您所见,我想存储具有不同语言环境的国家/地区。所以它有一个组合键。 address table 有一个指向 address_country 的外键。不幸的是,我无法设置 ContextDb 来实现我想要的。 Address 模型中未填写国家列表。
我在 Context 中有以下代码:

public class Context : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlite(
            @"Data Source=addresses.db");
        base.OnConfiguring(optionsBuilder);
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<AddressDto>()
            .ToTable("address");

        modelBuilder.Entity<CountryLocaleDto>()
            .ToTable("address_country");

        modelBuilder.Entity<CountryLocaleDto>()
            .HasKey(cl => new {cl.Id, cl.Locale});

        base.OnModelCreating(modelBuilder);
    }

    public DbSet<AddressDto> Addresses { get; set; }
}

我的模特是

public class AddressDto
{
    public int Id { get; set; }
    public int CountryId { get; set; }
    public List<CountryLocaleDto> CountryLocale { get; set; }
}
public class CountryLocaleDto
{
    public int Id { get; set; }
    public string Locale { get; set; }
}

也不例外。我根本不知道如何配置这种关系。有人可以帮我吗?

示例数据为:
地址

id countryId
1 1
2 1

address_country

id locale name
1 'en' 'Germany'
1 'de' 'Deutschland'

可以在 this link.

中找到使用 SQLite 数据库的示例解决方案

我现在明白你的问题了。如果 address 有一个指向 address_country 的外键,那么这意味着一个 AddressDto 只能有一个 CountryLocaleDto。如果你想要一个 address 连接到鬃毛 address_country,那么在你的 address_country 中你应该有一个外键到 address

如果你想建立多对多关系,那么你需要一个中介 table address_country_address

如果您使用第一个解决方案,那么您可以在 address_country 中添加 AddressId 列并像这样扩展 CountryLocaleDto

public class CountryLocaleDto
{
    public int Id { get; set; }
    public string Locale { get; set; }
    public int AddressId {get; set;}
}

然后执行以下操作?

modelBuilder.Entity<AddressDto>()
    .HasMany(c => c.CountryLocaleDto)
    .WithOne(a => a.AddressDto);
    .HasForeignKey(a => a.CountryId);
    .HasPrincipalKey(c => c.Id);

这通常是我们向 Many CountryLocale 声明一个地址的方式。

编辑

经过评论,我们发现address table.

中有一个CountryId列

由于我们需要将主键从一个更改为另一个,因此我们需要使用 alternate keys solution from microsoft.

Relationships that are discovered by convention will always target the primary key of the principal entity. To target an alternate key, additional configuration must be performed using the Fluent API.

    public class AddressDto
    {
        public int Id { get; set; }
        public int CountryId { get; set; }
        public List<CountryLocaleDto> CountryLocale { get; set; }
    }
    public class CountryLocaleDto
    {
        public int Id { get; set; }
        public string Locale { get; set; }
        public int AddressDtoId {get; set;}
        public AddressDto Address {get; set;}
    }

   modelBuilder.Entity<CountryLocaleDto>()
                .HasOne(p => p.Address)
                .WithMany(b => b.CountryLocale);

这里要配置一对多的关系,一个地址到多个国家

来源为:https://docs.microsoft.com/en-us/ef/core/modeling/relationships#fluent-api

您也可以这样做,并从 CountryLocaleDto 中删除 AddressDto 属性:

            modelBuilder.Entity<CountryLocaleDto>(model =>
            {
                model.HasOne<AddressDto>()
                      .WithMany()
                      .HasForeignKey(x => x.AddressDtoId);
            });

更新:

modelBuilder.Entity<AddressDto>()
                .HasMany(b => b.CountryLocale)
                .WithOne();

public class AddressDto
        {
            public int Id { get; set; }
            public int CountryId { get; set; }
            public List<CountryLocaleDto> CountryLocale { get; set; }
        }
        public class CountryLocaleDto
        {
            public int Id { get; set; }
            public string Locale { get; set; }
        }

来源:https://docs.microsoft.com/en-us/ef/core/modeling/relationships - 单一导航 属性

如果我猜对了 - 您只需将这段代码添加到您的上下文中 class

modelBuilder.Entity<AddressDto>()
            .HasMany(e=>e.CountryLocale)
            .WithOne()
            .HasForeignKey(x=>x.Id)
            .HasPrincipalKey(x=>x.CountryId);

这里要加上HasForeignKeyHasPrincipalKey

Entity Framework Core Fluent API HasForeignKey 方法用于指定属性 是关系中的外键。

主体密钥:唯一标识主体实体的属性(s)。这可能是主键或备用键。 导航属性:在主要and/or依赖实体上定义的属性,包含对相关实体的引用。

你的模型应该是这样的

public class AddressDto
{
    public int Id { get; set; }
    public int CountryId { get; set; }
    public List<CountryLocaleDto> CountryLocale { get; set; }
}
public class CountryLocaleDto
{
    public int Id { get; set; }
    public string Locale { get; set; }
}

我的意思是您不必在模型中添加任何其他内容。

希望对您有所帮助。

P.S。感谢添加示例项目