2016-08-18 6 views
0

Можно ли использовать POCOs и EF для работы со следующей ситуацией? Я хотел бы иметь таблицу транспортных средств с некоторыми полями bool, такими как IsFast, IsVan, IsTruck, а затем иметь класс транспортных средств с классом FastVehicle, Van, Truck, который наследует класс транспортных средств, не имея собственных таблиц, и без с полем дискриминатора?EntityFramework, унаследованные классы без дискриминатора

Что-то вроде:

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

Не использовал бы 'DbSet ', как вы предложили создавать таблицы для каждого 'DbSet'? Таким образом, у вас может быть 4 таблицы. Я бы просто придерживался только 'DbSet ' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' например 'Vans => Vehicles.Where (x => x.IsVan);' –

+0

Невозможно, не прибегая к большему количеству неприятностей, таких как конструкторы, которые принимают тип транспортного средства. почему ты хочешь сделать это? Я бы сказал, что вы создаете дискриминатор с вашими булерами, но вы просто не играете в мяч с Entity. –

+0

Возможно, этот подход не подходит для моих целей. Я искал функциональность, где экземпляр грузовика также может быть быстрым. Где я могу сделать что-то вроде 'bool fast = db.Trucks.Find (4) .IsFast' Возможно, мне нужно подумать о ситуации больше с точки зрения транспортных средств, которые могут иметь много ролей. – user868386

ответ

2

Если у вас нет дискриминатора или таблицы для каждого класса, это невозможно отличить ваши объекты.

Фактически вы можете опустить свойства bool, если они вам не нужны в вашей модели домена, поскольку Entity Framework по умолчанию использует таблицу для каждой иерархии, чтобы отображать наследование. Он автоматически создаст столбец дискриминатора для вас. Если вы добавите объект грузовика к своему DbSet, он соответствующим образом заполнит дискриминатор colomn.

http://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-1-table-per-hierarchy-tph

+0

Я бы хотел, чтобы что-то вроде Truck также было FastVehicle – user868386

+0

Я хотел бы добавить, что пометка '[NotMapped]' atrribute на вашем объекте, который наследуется от сопоставленной таблицы, позволит использовать его, а EF/.NET будет не искать столбец «Дискриминатор». – petersmm

0

EF может отображать это наследство автоматически, его легко и хорошо для производительности, вам не нужно беспокоиться о создании этой BOOL свойства.

Целая иерархия классов может быть отображена в одну таблицу. Эта таблица содержит столбцы для всех свойств всех классов в иерархии. Конкретный подкласс, представленный определенной строкой, идентифицируется значением столбца дискриминатора типа. Вам не нужно ничего делать в Code First, чтобы включить TPH. Это по умолчанию стратегия отображения наследования:

enter image description here

enter image description here

более

информации на http://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-1-table-per-hierarchy-tph

0

Я нашел решение для создания базы данных без столбца "Discriminator". Это решение подходит для ситуаций, когда мы хотим сохранить схему и таблицы базы данных, а также хотим добавить больше полей в некоторые объекты. Представьте, что вы хотите иметь базу данных для бизнеса A, и вы хотите использовать эту модель dbcontext для бизнеса B, тогда вы можете думать о своем наследовании на уровне базы данных и бизнеса.

OK

отпускает к решению:

предположить, что мы имеем

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 поэтому мое использование бизнес-логика может работать с любым из этих контекстов данных.

например, я хочу новую базу данных данных, которая совместима с текущей пользовательской бизнес-логикой, а также имеет дополнительные поля в пользовательской сущности. Мне нравится ниже:

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}"; 
    } 
} 

Надеюсь, это было полезно или дало вам хорошую идею.