ef 核心代码优先泛型继承映射
ef core code first generic inheritance mapping
所有职位都有一个位置(多对一)。
不同的Location类型有不同的Position类型
型号:
public abstract class Location
{
public int Id { get; set; }
public string Name { get; set; }
public int AreaId { get; set; }
public Area Area { get; set; }
public byte[] ConcurrencyToken { get; set; }
}
public abstract class Location<T> : Location where T : Position
{
public ICollection<T> Positions { get; set; } = new List<T>();
}
public class Bay : Location<BayRow> {}
public class StandardLocation : Location<Position> {}
public class Position
{
public int Id { get; set; }
public int? Place { get; set; }
public int LocationId { get; set; }
public Location Location { get; set; }
public byte[] ConcurrencyToken { get; set; }
}
public class BayRow : Position
{
public int? Row { get; set; }
}
以上是简写,每个都有很多实现。所有位置都扩展了通用 class.
映射:
modelBuilder.Entity<Position>(entity =>
{
entity.ToTable("Position")
.HasDiscriminator<int>("Type")
.HasValue<Position>(1)
.HasValue<BayRow>(2);
entity.Property(x => x.ConcurrencyToken).IsConcurrencyToken();
//THIS IS THE ISSUE*
entity.HasOne(x => x.Location as Location<Position>).WithMany(x => x.Positions).HasForeignKey(x => x.LocationId);
});
modelBuilder.Entity<Location>(entity =>
{
entity.HasIndex(x => new {x.Name, x.AreaId}).IsUnique(true);
entity.Property(x => x.ConcurrencyToken).IsConcurrencyToken();
entity.HasDiscriminator<int>("Type")
.HasValue<StandardLocation>(1)
.HasValue<Bay<BayRow>>(2)
});
modelBuilder.Entity<Bay<BayRow>>(entity =>
{
entity.HasMany(x => x.Positions).WithOne(x => x.Location as Bay<BayRow>)
.HasForeignKey(x => x.LocationId).OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity<BayRow>(entity =>
{
entity.Property(x => x.Row).HasColumnName("Row");
});
*非通用位置没有位置
我已经尝试将集合添加到基本位置纯粹用于映射,以避免 ef duplicating/aliasing 每个位置 Impl,即 BayId 作为 LocationId。
publiic ICollection<Position> Positions { get; set; }
并使用 new 关键字隐藏基本集合,但 ef 项目 2 个集合...
public new ICollection<T> Positions { get; set; }
如有任何见解,我们将不胜感激。
我不确定 Entity Framework 是否支持此功能,而没有生成两张表 - 一张用于 Bay,一张用于 StandardLocation。
您可以试试这个作为解决方法。
public interface ITypedPosition<T> where T: Position
{
IEnumerable<T> Positions { get; }
}
public abstract class Location
{
public int Id { get; set; }
public string Name { get; set; }
public int AreaId { get; set; }
public Area Area { get; set; }
public byte[] ConcurrencyToken { get; set; }
public ICollection<Position> Positions { get; set; }
}
public class Bay : Location, ITypedPosition<BayRow>
{
IEnumerable<BayRow> ITypedPosition<BayRow>.Positions => base.Positions.OfType<BayRow>();
}
public class StandardLocation : Location, ITypedPosition<Position>
{
IEnumerable<Position> ITypedPosition<Position>.Positions => base.Positions.OfType<Position>();
}
所有职位都有一个位置(多对一)。 不同的Location类型有不同的Position类型
型号:
public abstract class Location
{
public int Id { get; set; }
public string Name { get; set; }
public int AreaId { get; set; }
public Area Area { get; set; }
public byte[] ConcurrencyToken { get; set; }
}
public abstract class Location<T> : Location where T : Position
{
public ICollection<T> Positions { get; set; } = new List<T>();
}
public class Bay : Location<BayRow> {}
public class StandardLocation : Location<Position> {}
public class Position
{
public int Id { get; set; }
public int? Place { get; set; }
public int LocationId { get; set; }
public Location Location { get; set; }
public byte[] ConcurrencyToken { get; set; }
}
public class BayRow : Position
{
public int? Row { get; set; }
}
以上是简写,每个都有很多实现。所有位置都扩展了通用 class.
映射:
modelBuilder.Entity<Position>(entity =>
{
entity.ToTable("Position")
.HasDiscriminator<int>("Type")
.HasValue<Position>(1)
.HasValue<BayRow>(2);
entity.Property(x => x.ConcurrencyToken).IsConcurrencyToken();
//THIS IS THE ISSUE*
entity.HasOne(x => x.Location as Location<Position>).WithMany(x => x.Positions).HasForeignKey(x => x.LocationId);
});
modelBuilder.Entity<Location>(entity =>
{
entity.HasIndex(x => new {x.Name, x.AreaId}).IsUnique(true);
entity.Property(x => x.ConcurrencyToken).IsConcurrencyToken();
entity.HasDiscriminator<int>("Type")
.HasValue<StandardLocation>(1)
.HasValue<Bay<BayRow>>(2)
});
modelBuilder.Entity<Bay<BayRow>>(entity =>
{
entity.HasMany(x => x.Positions).WithOne(x => x.Location as Bay<BayRow>)
.HasForeignKey(x => x.LocationId).OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity<BayRow>(entity =>
{
entity.Property(x => x.Row).HasColumnName("Row");
});
*非通用位置没有位置
我已经尝试将集合添加到基本位置纯粹用于映射,以避免 ef duplicating/aliasing 每个位置 Impl,即 BayId 作为 LocationId。
publiic ICollection<Position> Positions { get; set; }
并使用 new 关键字隐藏基本集合,但 ef 项目 2 个集合...
public new ICollection<T> Positions { get; set; }
如有任何见解,我们将不胜感激。
我不确定 Entity Framework 是否支持此功能,而没有生成两张表 - 一张用于 Bay,一张用于 StandardLocation。
您可以试试这个作为解决方法。
public interface ITypedPosition<T> where T: Position
{
IEnumerable<T> Positions { get; }
}
public abstract class Location
{
public int Id { get; set; }
public string Name { get; set; }
public int AreaId { get; set; }
public Area Area { get; set; }
public byte[] ConcurrencyToken { get; set; }
public ICollection<Position> Positions { get; set; }
}
public class Bay : Location, ITypedPosition<BayRow>
{
IEnumerable<BayRow> ITypedPosition<BayRow>.Positions => base.Positions.OfType<BayRow>();
}
public class StandardLocation : Location, ITypedPosition<Position>
{
IEnumerable<Position> ITypedPosition<Position>.Positions => base.Positions.OfType<Position>();
}