C# EntityFramework,不带鉴别器的继承类

C# EntityFramework,不带鉴别器的继承类,c#,entity-framework,entity-framework-6,C#,Entity Framework,Entity Framework 6,是否可以使用POCOs和EF处理以下情况?我希望有一个Vehicles表,带有一些布尔字段,如IsFast、IsVan、IsTruck,然后有一个Vehicles类,有一个从Vehicles类继承的FastVehicle、Van、Truck类,没有自己的表,也没有鉴别器字段 比如: public class Vehicle { public int Id {get; set;} public bool IsFast {get; set;} public bool IsTr

是否可以使用POCOs和EF处理以下情况?我希望有一个Vehicles表,带有一些布尔字段,如IsFast、IsVan、IsTruck,然后有一个Vehicles类,有一个从Vehicles类继承的FastVehicle、Van、Truck类,没有自己的表,也没有鉴别器字段

比如:

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;
    }
}
然后,在我的背景中,可能会有如下内容:

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);
公共虚拟数据库集车辆{get;set;}
公共虚拟DbSet-Vans=>(DbSet)车辆。其中(v=>IsVan);
公共虚拟DbSet卡车=>(DbSet)车辆。其中(v=>IsTruck);
公共虚拟DbSet FastVehicles=>(DbSet)车辆。其中(v=>isfastVehicles);

这样的事情可能吗?或者出于某种原因这是个坏主意?如何覆盖模型创建

如果每个类都没有一个鉴别器或表,就无法区分实体

如果域模型中不需要bool属性,实际上可以省略它们,因为实体框架使用每个层次的表作为默认映射继承。它将自动为您创建一个鉴别器列。 如果将卡车对象添加到数据库集中,它将相应地填充鉴别器列


EF可以自动映射此继承,它简单且性能良好,您无需担心创建此布尔属性

整个类层次结构可以映射到单个表。此表包含层次结构中所有类的所有属性的列。由特定行表示的具体子类由类型鉴别器列的值标识。您不必首先在代码中执行任何特殊操作来启用TPH。这是默认的继承映射策略:

更多信息请访问

我找到了一种不使用“鉴别器”列生成数据库的解决方案。 此解决方案适用于我们希望保留数据库模式和表,以及希望在某些实体中添加更多字段的情况。 假设您想要为业务a拥有一个数据库,并且想要为业务B使用这个dbcontext模型,那么您可以将数据库和业务级别的继承考虑在一起

让我们转到解决方案:

假设我们有

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}";
}
公共类SampleDataContext:DbContext
{
公共数据库集用户{get;set;}
}
[表(“用户”)]
公共类抽样用户
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共字符串族{get;set;}
公共字符串用户名{get;set;}
公共重写字符串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);
}
公共接口IDbContext
{
int SaveChanges();
}
公共接口IDbSet
{
TE Add();
IQueryable All();
TE Get(TId id);
作废删除(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类SampleDataContext:DbContext,IUserDbContext
{
公共数据库集用户{get;set;}
私有IDbSet _用户集;
公共IDbSet用户集
{
获取{return\u userSet??(\u userSet=new UserInterface(){Db=this});}
set{u userSet=value;}
}
公共类用户接口:IDbSet
{
公共SampleDataContext数据库{get;set;}
public SampleUser Add()=>Db.Users.Add(new SampleUser());
public IQueryable 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:IDbContext { IDbSet用户集{get;set;} } 然后,我的逻辑业务接受IUserDbContext而不是SampleDataContext

公共静态列表ListUsers(IUserDbContext db)
{
返回db.UserSet.All().ToList();
}
通过这种方法,我可以拥有许多具有自由结构的数据库,并实现IUserDbContext,这样我的使用业务逻辑就可以处理这些数据上下文中的任何一个

例如,我想要一个与当前用户业务逻辑兼容的新数据上下文库,并且在用户实体上有额外的字段。我确实喜欢以下内容:

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}";
    }
}
公共类MyDataContext:DbContext,IUserDbContext { 公共数据库集用户{get;set;} 私有IDbSet _用户集; 公共IDbSet用户集 { 获取{return\u userSet??(\u userSet=new UserInterface(){Db=this});} set{u userSet=value;} } 公共类用户接口:IDbSet { 公共MyDataContext数据库{get;set;} public SampleUser Add()=>Db.Users.Add(new MyUser()); public IQueryable 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()); } } [表(“用户”)] 公共类MyUser:SampleUser { 公共字符串颜色{get;set;} 公共重写字符串ToString() { 返回base.ToString()+$“/color:{color}”; } }
我希望这是有用的或给你任何好主意。

目前在新的EF中,设计非常狡猾。它们使用鉴别器字段。 如果您想要使用从基表继承的单独表的老式方法,那么 您正在寻找每种类型的表实现

以下是有关如何实现该功能的教程:

是否会像您建议的那样使用
DbSet
为每个
DbSet
创建表?这样你就可以有4张桌子了。我会坚持使用名为
Vehicles
DbSet
,并在您的DbConte中具有标准属性
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}";
    }
}