我必须使用以下架构支持第三方数据库(看起来像RoR样式?)。
这是主表车辆,其中 VehicleType 是一个鉴别器(可能的值为'Car'
和'Bike'
)。因此,如果 VehicleType = 'Car'
,则 SubId 指向 Car 表中的记录,如果 VehicleType = 'Bike'
然后将积分记录到自行车表。
并且加表不共享主键值。
我想避免在我的代码中使用复杂的逻辑,但是我无法理解我是否可以在这里使用继承(所以Car : Vehicle
和Bike : Vehicle
)或者至少是导航属性(所以{{1} }和Car.Vehicle
可以工作)。所以问题是我可以使用这个吗?如何实现这个?
答案 0 :(得分:1)
表格不共享主键值
因此,无法将此映射到一个继承架构,该架构本应为TPT。不同的主键值会阻止这种情况。
剩下的是映射彼此连接的不同类,因此您至少可以使用导航属性而不是手动加入不相关的实体。我找到了一种方法来做到这一点,但它并不理想。实际上,它是非常做作的。但是看看它是否适合您。
我使用了这些课程:
public abstract class Vehicle
{
public int VehicleId { get; set; }
public string Name { get; set; }
public VehicleInfo VehicleInfo { get; set; }
}
public class CarVehicle : Vehicle
{ }
public class BikeVehicle : Vehicle
{ }
public abstract class VehicleInfo
{
public int ID { get; set; }
}
public class CarInfo : VehicleInfo
{
public string Model { get; set; }
}
public class BikeInfo : VehicleInfo
{
public bool IsEbike { get; set; }
}
我将表格Vehicle
分成CarVehicle
实体BikeVehicle
和modelBuilder.Entity<Vehicle>().ToTable("Vehicle");
modelBuilder.Entity<Vehicle>()
.Map<CarVehicle>(m => m.Requires("VehicleType").HasValue("Car"))
.Map<BikeVehicle>(m => m.Requires("VehicleType").HasValue("Bike")
.HasColumnType("CHAR")
.HasMaxLength(4));
TPH:
CarInfo
另一方面, BikeInfo
和modelBuilder.Entity<VehicleInfo>()
.Map<CarInfo>(c =>
{
c.MapInheritedProperties().ToTable("Car");
c.Property(x => x.ID).HasColumnName("CarId");
c.Property(x => x.Model);
})
.Map<BikeInfo>(c =>
{
c.MapInheritedProperties().ToTable("Bike");
c.Property(x => x.ID).HasColumnName("BikeId");
c.Property(x => x.IsEbike);
});
必须有自己的表格,所以我在这里使用了TPC:
modelBuilder.Entity<Vehicle>().HasRequired(c => c.VehicleInfo)
.WithOptional().Map(m => m.MapKey("SubId"));
最后,连接课程:
VehicleInfo
通过使用基本类型Vehicle.VehicleInfo
,可以通过一个外键SubId
映射一个属性public class CarVehicle : Vehicle
{
public CarInfo CarInfo { get; set; }
}
public class BikeVehicle : Vehicle
{
public BikeInfo BikeInfo { get; set; }
}
。这是不可能的:
SubId
如果您尝试通过VehicleInfo
映射两个导航属性,则EF不会接受它。
这种模式的主要缺点是你总是必须得到信息&#34;信息&#34;实体为VehicleInfo
个对象。 EF将创建正确的子类型,但它们的编译时类型为VehicleInfo
。同样,如果设置public class CarVehicle : Vehicle
{
[NotMapped]
public CarInfo CarInfo
{
get { return VehicleInfo as CarInfo; }
set { VehicleInfo = value; }
}
}
属性,则必须记住提供正确的类型。您可以通过传递属性来缓解这种情况......
BikeVehicle
...和db.Set<CarVehicle>().Include(c => c.VehicleInfo).ToList();
中的相同。但是您无法直接在LINQ查询中使用此属性,因为它不是(并且无法)映射。
此外,执行的SQL来自简单的...
[HttpGet]
由于EF挖掘了所有继承树,所以......是非常棒的。