是否可以使用POCO和EF来处理以下情况?我想有一个车辆表,有一些bool字段,如IsFast,IsVan,IsTruck,然后有一个车辆类,有一个FastVehicle,Van,Truck类继承自Vehicles类,没有自己的表,没有有鉴别领域?
类似的东西:
public class Vehicle
{
public int Id {get; set;}
public bool IsFast {get; set;}
public bool IsTruck {get; set;}
public bool IsVan {get; set;}
}
public class FastVehicle : Vehicle
{
public FastVehicle(){
IsFast = true;
}
}
public class Van: Vehicle{
public Van(){
IsVan = true;
}
}
public class Truck : Vehicle
{
public Truck(){
IsTruck = true;
}
}
然后可能在我的DbContext中有类似的东西:
public virtual DbSet<Vehicle> Vehicles {get; set;}
public virtual DbSet<Van> Vans => (DbSet<Van>) Vehicles.Where(v => IsVan);
public virtual DbSet<Truck> Trucks => (DbSet<Truck>) Vehicles.Where(v => IsTruck);
public virtual DbSet<FastVehicle> FastVehicles => (DbSet<FastVehicle>) Vehicles.Where(v => IsFastVehicle);
这样的事情可能吗?或者出于某种原因这是个坏主意?我将如何重写OnModelCreating?
答案 0 :(得分:2)
如果您没有每个班级的鉴别器或表格,则无法区分您的实体。
如果您在域模型中不需要bool属性,则实际上可以省略它们,因为Entity Framework默认使用Table per Hierarchy来映射继承。它会自动为您创建一个鉴别器列。 如果您将卡车对象添加到DbSet,它将相应地填充鉴别器colomn。
答案 1 :(得分:1)
我找到了一个生成数据库的解决方案,没有&#34; Discriminator&#34;柱。 此解决方案适用于我们希望保留数据库模式和表的情况,并且我们还希望在某些实体中添加更多字段。 想象一下,您希望拥有一个用于业务A的数据库,并且您希望将此dbcontext模型用于业务B,那么您可以在数据库和业务级别中一起考虑一种继承。
行
让我们去解决方案:
假设我们有
public class SampleDataContext : DbContext
{
public DbSet<SampleUser> Users { get; set; }
}
[Table("Users")]
public class SampleUser
{
public int Id { get; set; }
public string Name { get; set; }
public string Family { get; set; }
public string Username { get; set; }
public override string ToString() => $"{Username} : {Name} {Family}";
}
我想在用户实体上创建一个带有额外字段的新数据上下文。新数据上下文也必须与我当前的业务逻辑层完全兼容。
我建议使用如下界面:
public interface IDbContext
{
int SaveChanges();
}
public interface IDbSet<TE, in TId>
{
TE Add();
IQueryable<TE> All();
TE Get(TId id);
void Delete(TId id);
}
并像这样更改 SampleDataContext :
public class SampleDataContext : DbContext,IUserDbContext
{
public DbSet<SampleUser> Users { get; set; }
private IDbSet<SampleUser, int> _userSet;
public IDbSet<SampleUser, int> UserSet
{
get { return _userSet ?? (_userSet = new UserInterface() { Db = this }); }
set { _userSet = value; }
}
public class UserInterface : IDbSet<SampleUser, int>
{
public SampleDataContext Db { get; set; }
public SampleUser Add() => Db.Users.Add(new SampleUser());
public IQueryable<SampleUser> All() => Db.Users;
public SampleUser Get(int id) => Db.Users.Find(id);
public void Delete(int id) => Db.Users.Remove(Get(id));
}
}
还为用户业务添加界面:
public interface IUserDbContext : IDbContext
{
IDbSet<SampleUser, int> UserSet { get; set; }
}
然后我的逻辑业务接受 IUserDbContext 而不是 SampleDataContext 。
public static List<SampleUser> ListUsers(IUserDbContext db)
{
return db.UserSet.All().ToList();
}
通过这种方法,我可以拥有许多具有自由结构的数据库并实现 IUserDbContext ,因此我的使用业务逻辑可以与任何这些数据上下文一起使用。
例如,我想要一个与当前用户业务逻辑兼容的新数据上下文库,并且在User实体上还有额外的字段。我喜欢以下内容:
public class MyDataContext : DbContext, IUserDbContext
{
public DbSet<MyUser> Users { get; set; }
private IDbSet<SampleUser, int> _userSet;
public IDbSet<SampleUser, int> UserSet
{
get { return _userSet ?? (_userSet = new UserInterface() { Db = this }); }
set { _userSet = value; }
}
public class UserInterface : IDbSet<SampleUser, int>
{
public MyDataContext Db { get; set; }
public SampleUser Add() => Db.Users.Add(new MyUser());
public IQueryable<SampleUser> All() => Db.Users;
public SampleUser Get(int id) => Db.Users.Find(id);
public void Delete(int id) => Db.Users.Remove(Db.Users.Find(id)??new MyUser());
}
}
[Table("Users")]
public class MyUser : SampleUser
{
public string Color { get; set; }
public override string ToString()
{
return base.ToString() + $"/ color : {Color}";
}
}
我希望这很有用,或者给你一个好主意。
答案 2 :(得分:0)
当前,在新的EF中,设计非常狡猾。他们使用区分字段。 如果您希望使用从基表继承的单独表的旧方法,则 您正在寻找每种类型的表格实现。
这里是有关如何实现该目标的教程: https://weblogs.thinktecture.com/pawel/2018/05/entity-framework-core-inheritance-table-per-type-tpt-is-not-supported-is-it-part-2-database-first.html
答案 3 :(得分:-1)
EF可以自动映射这个继承,它很容易并且对性能有好处,你不必担心创建这个bool属性。
整个类层次结构可以映射到单个表。此表包含层次结构中所有类的所有属性的列。由特定行表示的具体子类由类型鉴别器列的值标识。您无需在Code First中执行任何特殊操作即可启用TPH。它是默认的继承映射策略: