简体   繁体   English

EF Core 中的导航映射问题

[英]Navigation mapping issues in EF Core

I'm trying to achieve the following layout:我正在尝试实现以下布局:

User table (has link to user details) User details table (holds links to various detail tables)用户表(包含指向用户详细信息的链接) 用户详细信息表(包含指向各种详细信息表的链接)

but am getting the following error:但我收到以下错误:

System.InvalidOperationException: Cannot create a relationship between 'Address.ClientDetails' and 'ClientDetails.ResidentialAddress', because there already is a relationship between 'ClientDetails.PostalAddress' and 'Address.ClientDetails'. Navigation properties can only participate in a single relationship.

I understand this problem would occur if entity framework had no way to identify which address to link to each address - but i thought i take care of that by specifying 2 links in the model and then each key map in the mapping class.我知道如果实体框架无法识别要链接到每个地址的地址,则会出现此问题 - 但我认为我通过在 model 中指定 2 个链接然后在映射 ZA2F2ED4F8EBC2CBB4C21A29D. Any help would be great!任何帮助都会很棒!

my Client model and mapping looks as follows:我的客户端 model 和映射如下所示:

public class Client : BaseEntity
    {
        public ClientDetails ApplicantDetails
        {
            get
            {
                return this.ClientDetails.SingleOrDefault(e => e.ClientType == Enums.ClientType.Applicant.ToString());
            }
        }

    public ClientDetails SpouseDetails
    {
        get
        {
            return this.ClientDetails.SingleOrDefault(e => e.ClientType == Enums.ClientType.Spouse.ToString());
        }
    }
    public ICollection<ClientDetails> ClientDetails { get; set; }
    public ICollection<BankDetails> BankDetails { get; set; }
    public ICollection<Expenses> Expenses { get; set; }
    public ICollection<Obligation> Obligations { get; set; }
    public ICollection<Budget> Budgets { get; set; }
    public ICollection<Document.Document> Documents { get; set; }
    public virtual Workflow.Workflow Workflow { get; set; }

Mapping映射

public class ClientMapping: IEntityTypeConfiguration<Entities.Client.Client>
{
    public void Configure(EntityTypeBuilder<Entities.Client.Client> builder)
    {
        builder.ToTable("Client");
        builder.HasKey(e => e.Id);
        builder.HasMany(e => e.ClientDetails).WithOne(e => e.Client).HasForeignKey(e => e.ClientId);
        builder.HasMany(e => e.Documents).WithOne(e => e.Client).HasForeignKey(e => e.ClientId);
        builder.HasOne(e => e.Workflow).WithOne(e => e.Client).HasForeignKey<Entities.Workflow.Workflow>(e => e.ClientId);
        builder.HasMany(e => e.Obligations).WithOne(e => e.Client).HasForeignKey(e => e.ClientId);
        builder.HasMany(e => e.Expenses).WithOne(e => e.Client).HasForeignKey(e => e.ClientId);
        builder.HasMany(e => e.Budgets).WithOne(e => e.Client).HasForeignKey(e => e.ClientId);
        builder.HasMany(e => e.BankDetails).WithOne(e => e.Client).HasForeignKey(e => e.ClientId);

        builder.Ignore(e => e.ApplicantDetails);
        builder.Ignore(e => e.SpouseDetails);
    }
}

Client Details and mapping客户详细信息和映射

public class ClientDetails
    {
        public int ClientId { get; set; }
        public int PersonalDetailsId { get; set; }
        public int EmployerId { get; set; }
        public int ResidentialAddressId { get; set; }
        public int PostalAddressId { get; set; }
        public int IncomeId { get; set; }
        public string ClientType { get; set; }
        public virtual Client Client { get; set; }
        public virtual PersonalDetails PersonalDetails { get; set; }
        public virtual Employer Employer { get; set; }
        public virtual Address ResidentialAddress { get; set; }
        public virtual Address PostalAddress { get; set; }
        public virtual Income Income { get; set; }
    }

mapping映射

public class ClientDetailsMapping : IEntityTypeConfiguration<Entities.Client.ClientDetails>
    {
        public void Configure(EntityTypeBuilder<ClientDetails> builder)
        {
            builder.ToTable("ClientDetails");
            builder.HasKey(e => new { e.IncomeId, e.PersonalDetailsId, e.ClientId, e.PostalAddressId, e.ResidentialAddressId } );
            builder.HasOne(e => e.Income).WithOne(e => e.ClientDetails).HasForeignKey<ClientDetails>(e => e.IncomeId);
            builder.HasOne(e => e.PostalAddress).WithOne(e => e.ClientDetails).HasForeignKey<ClientDetails>(e => e.PostalAddressId);
            builder.HasOne(e => e.ResidentialAddress).WithOne(e => e.ClientDetails).HasForeignKey<ClientDetails>(e => e.ResidentialAddressId);
            builder.HasOne(e => e.Employer).WithOne(e => e.ClientDetails).HasForeignKey<ClientDetails>(e => e.EmployerId);
            builder.HasOne(e => e.PersonalDetails).WithOne(e => e.ClientDetails).HasForeignKey<ClientDetails>(e => e.PersonalDetailsId);
        }
    }

Can you try to delete the content of "WithOne"?你可以尝试删除“WithOne”的内容吗?

try this:尝试这个:

builder.HasOne(e => e.PostalAddress).WithOne().HasForeignKey<ClientDetails>(e => e.PostalAddressId);
builder.HasOne(e => e.ResidentialAddress).WithOne().HasForeignKey<ClientDetails>(e => e.ResidentialAddressId);

Found this post:找到这个帖子:

ef core - two one to one on one principal key ef core - 两个一对一的主键

Ended up implementing solution 3, client details now has a collection of addresses (which have an address type linked), I then added an address getter on the client details to get the address I want at a later time.最终实现了解决方案 3,客户端详细信息现在有一个地址集合(其中链接了一个地址类型),然后我在客户端详细信息上添加了一个地址获取器,以便稍后获取我想要的地址。 Everything seems to work correctly now.现在一切似乎都正常工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM