簡體   English   中英

實體框架和自引用 collections

[英]Entity Framework and self-referencing collections

我正在嘗試 model 一個位置 object。 位置可以運送到許多其他位置並從許多位置接收。 位置也可以有一個父位置。 如何通過實體框架在我的數據庫中表示它? 這是我到目前為止所擁有的:位置 Class:

public class Location
{
    public int Id { get; set; }

    public string Name { get; set; }
    
    public string ShortName { get; set; }

    public Location ParentLocation { get; set; }

    public int? ParentLocationId { get; set; }

    public ICollection<Location> ShipToLocations { get; set; }
    public ICollection<Location> ReceiveFromLocations { get; set; }
    
}

OnModelCreating function 在我的 DbContext class 中:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
   modelBuilder.Entity<Location>(entity =>
   {
       entity.HasKey(x => x.Id);
       entity.HasOne(x => x.ParentLocation);
       entity.HasMany(x => x.ShipToLocations);
       entity.HasMany(x => x.ReceiveFromLocations);
    });
}

我似乎正在通過數據庫獲取 ParentLocationId 字段,這對我來說很有意義。 但是,ef 也會為數據庫生成 LocationId 和 LocationId1 字段,這是沒有意義的。 我理解它的方式,實體框架應該生成某種形式的連接表,因為每個位置都有許多運送到位置的位置和許多從位置接收的位置,所有這些位置都是其他位置。

由於您嘗試使用單個表進行此操作,因此 EF 嘗試為目標和源位置創建額外的外鍵。 您實際上無法通過一張桌子實現這一目標。 您應該有一個附加表,表示該位置可用的目的地。

你應該嘗試像這樣構建你的類:

public class Location
{
    public int Id { get; set; }

    // other fields here
    
    public int? ParentId { get; set; }
    public Location Parent { get; set; }

    public ICollection<Location> ChildLocations { get; } 
    
    public ICollection<LocationDestintaion> Destinations { get; set; }
    
    public ICollection<LocationDestintaion> Sources { get; set; }
}

public class LocationDestintaion
{
    public int SourceId { get; set; }
    public Location Source { get; set; }
    
    public int DestinationId { get; set; }
    public Location Destination { get; set; }
}

然后您將擁有這種ModelBuilder配置:

modelBuilder.Entity<Location>()
            .HasOne(x => x.Parent).WithMany(x => x.ChildLocations)
            .HasForeignKey(x => x.ParentId).IsRequired(false);

modelBuilder.Entity<Location>()
            .HasMany(x => x.Destinations).WithOne(x => x.Source)
            .HasForeignKey(x => x.SourceId);
        
modelBuilder.Entity<Location>()
            .HasMany(x => x.Sources).WithOne(x => x.Destination)
            .HasForeignKey(x => x.DestinationId);

modelBuilder.Entity<LocationDestintaion>().ToTable("Paths")
            .HasKey(x => new {x.SourceId, x.DestinationId});

然后,您可以像這樣查詢目的地和來源:

const int locationId = 1;

var availableDestinations = context.Locations.Where(x => x.Id == locationId)
            .SelectMany(x => x.Destinations).ToList();

var sourceLocations = context.Locations.Where(x => x.Id == locationId)
            .SelectMany(x => x.Sources).ToList();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM