简体   繁体   中英

EF Core multiple navigation properties to same table with fluent api

I searched a lot but no luck to find a solution to my entities.

I have 2 entities. Device & PersonEnterExit I have 2 Collection of PersonEnterExit in Device entity. When I run database update it says me you have same entity with different name. do manually name them. how do i do that? I want to do this with fluent api in onModelCreating.

Devices.cs

using System;
using System.Collections.Generic;

namespace DesTech.Core.Entities
{
    public class Device : BaseEntity
    {
        public bool? IsConnected { get; set; }
        public string Name { get; set; }
        public string Ip { get; set; }
        public int Port { get; set; }
        public DateTime? LastConnectTime { get; set; }
        public DateTime? ChangeClockBatteryWarningTime { get; set; }
        public bool HasFp { get; set; }

        public virtual Location Location { get; set; }
        public virtual ICollection<DeviceOptLog> DeviceOptLog { get; set; }
        public virtual ICollection<DevicePerson> DevicePerson { get; set; }
        public virtual ICollection<DeviceTimeZone> DeviceTimeZone { get; set; }
        public virtual ICollection<PersonEnterExit> PersonEnterExitEnDevice { get; set; }
        public virtual ICollection<PersonEnterExit> PersonEnterExitExDevice { get; set; }
        public virtual ICollection<PersonPassLog> PersonPassLog { get; set; }
    }
}

PersonEnterExit.cs

using System;

namespace DesTech.Core.Entities
{
    public class PersonEnterExit : BaseEntity
    {
        public int Type { get; set; }
        public int? PersonId { get; set; }
        public DateTime? NoEnterTime { get; set; }
        public int? EnDeviceId { get; set; }
        public DateTime? EnVerifyDate { get; set; }
        public string EnPlate { get; set; }
        public int? ExDeviceId { get; set; }
        public DateTime? ExVerifyDate { get; set; }

        public virtual Device EnDevice { get; set; }
        public virtual Device ExDevice { get; set; }
        public virtual Person Person { get; set; }

    }
}

Like you mentioned, you need to explicitly configure both relationships. Otherwise, EF will get confused.

build.Entity<PersonEnterExit>()
     .HasOne(e => e.EnDevice)
     .WithMany(d => d.PersonEnterExitEnDevice);

build.Entity<PersonEnterExit>()
     .HasOne(e => e.ExDevice)
     .WithMany(d => d.PersonEnterExitExDevice);

See if this helps. You may need to explicitly configure foreign keys if this doesn't work.

You can use one of these

  1. FluentApi
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Device>()
        .HasMany(a => a.PersonEnterExitEnDevice)
        .WithOne(a => a.EnDevice)
        .HasForeignKey(a => a.EnDeviceId).OnDelete(DeleteBehavior.Restrict); 

    modelBuilder.Entity<Device>()
        .HasMany(a => a.PersonEnterExitExDevice)
        .WithOne(a => a.ExDevice)
        .HasForeignKey(a => a.ExDeviceId).OnDelete(DeleteBehavior.Restrict); 
}
  1. Metadata . you can use InverseProperty to define the relationships.
namespace DesTech.Core.Entities
{
    public class PersonEnterExit : BaseEntity
    {
        public int Type { get; set; }
        public int? PersonId { get; set; }
        public DateTime? NoEnterTime { get; set; }
        public int? EnDeviceId { get; set; }
        public DateTime? EnVerifyDate { get; set; }
        public string EnPlate { get; set; }
        public int? ExDeviceId { get; set; }
        public DateTime? ExVerifyDate { get; set; }
        [InverseProperty("PersonEnterExitEnDevice")]
        public virtual Device EnDevice { get; set; }
        [InverseProperty("PersonEnterExitExDevice")]
        public virtual Device ExDevice { get; set; }
        public virtual Person Person { get; set; }

    }
}
namespace DesTech.Core.Entities
{
    public class Device : BaseEntity
    {
        public bool? IsConnected { get; set; }
        public string Name { get; set; }
        public string Ip { get; set; }
        public int Port { get; set; }
        public DateTime? LastConnectTime { get; set; }
        public DateTime? ChangeClockBatteryWarningTime { get; set; }
        public bool HasFp { get; set; }

        public virtual Location Location { get; set; }
        public virtual ICollection<DeviceOptLog> DeviceOptLog { get; set; }
        public virtual ICollection<DevicePerson> DevicePerson { get; set; }
        public virtual ICollection<DeviceTimeZone> DeviceTimeZone { get; set; }
        [InverseProperty("EnDevice")]
        public virtual ICollection<PersonEnterExit> PersonEnterExitEnDevice { get; set; }
        [InverseProperty("ExDevice")]
        public virtual ICollection<PersonEnterExit> PersonEnterExitExDevice { get; set; }
        public virtual ICollection<PersonPassLog> PersonPassLog { get; set; }
    }
}

Okey I combined two answers and its works now. I reply my question for maybe others use same approach. If i mistake please warn me. But it works now.

        builder.HasMany(a => a.PersonEnterExitEnDevice)
            .WithOne(a => a.EnDevice)
            .HasForeignKey(a => a.EnDeviceId)
            .OnDelete(DeleteBehavior.Restrict); 

        builder.HasMany(a => a.PersonEnterExitExDevice)
            .WithOne(a => a.ExDevice)
            .HasForeignKey(a => a.ExDeviceId)
            .OnDelete(DeleteBehavior.Restrict); 


        builder.HasOne(d => d.EnDevice)
            .WithMany(e => e.PersonEnterExitEnDevice)
            .HasForeignKey(d => d.EnDeviceId)
            .HasConstraintName("FK_PersonEnterExit_DeviceEn");

        builder.HasOne(d => d.EnLocation)
            .WithMany(e => e.PersonEnterExitEnLocation)
            .HasForeignKey(d => d.EnLocationId)
            .HasConstraintName("FK_PersonEnterExit_LocationEx");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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