[英]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.