2012-05-02 13 views
5

tengo los siguientes tipos:Consulta por tipo de base en EF4 Código-Primera

public abstract class Vehicle { 
    public int Id { get; set; } 
    public double TopSpeed { get; set; } 
} 

public class Car : Vehicle { 
    public int Doors { get; set; } 
} 

public class Motorcycle : Vehicle { 
    public string Color { get; set; } 
} 

Y tengo un código de primera DBContext:

public MyDbContext: DbContext { 
    public DbSet<Car> Cars { get; set; } 
    public DbSet<Motorcycle> Motorcycles { get; set; } 
} 

Esto funciona muy bien si la consulta para un coche o directamente moto ...

var dbContext = new MyDbContext(); 
var cars = dbContext.Set<Car>().Where(x=> x.TopSpeed>10); // <-- THIS WORKS 

Pero si quiero una lista de todos los vehículos, ya sea coche o moto, me gustaría hacer esto:

var dbContext = new MyDbContext(); 
var vehicles = dbContext.Set<Vehicle>().Where(x=> x.TopSpeed>10); // <-- THIS DOES NOT WORK 

Cuando intento el código anterior, me sale una excepción:

System.InvalidOperationException: El tipo de entidad vehículo no es parte del modelo para el contexto actual.

Eso tiene perfecto sentido ... No agregué el vehículo al contexto. Añadí coche y moto. En este punto, no estoy seguro de qué hacer. Intenté agregar Vehículo a mi contexto, pero eso combinó las tablas para automóvil y moto en una sola tabla de Vehículo. Definitivamente quiero una mesa separada para autos y motos (y posiblemente una mesa para las propiedades de base del vehículo también). ¿Cuál es la mejor manera de hacer esto?

+0

EF no es lo mío, pero ¿podría obtener un conjunto a través de la interfaz si lo agrega al contexto, p. cambiar 'Vehicle' a' IVehicle'? – Eli

Respuesta

11

Tiene un Propiedades de vehículos del tipo DBSet de Vehicle en su clase MyDbContext.

public MyDbContext: DbContext { 
    public DbSet<Car> Cars { get; set; } 
    public DbSet<Motorcycle> Motorcycles { get; set; } 
    public DbSet<Vehicle> Vehicles { set; get; } 
} 

Ahora puede acceder a todos los vehículos con los criterios de esta manera

var vehicles = dbContext.Set<Vehicle>().Where(x=> x.TopSpeed>10); 

Tenga en cuenta que usted debe tener una propiedad clave en sus clases de entidad (o ID{ClassName}ID). ¡De lo contrario, te dará un error de tiempo de ejecución! (Si el código se compilará.)

public abstract class Vehicle 
{ 
    public int ID { set; get; } 
    public double TopSpeed { get; set; } 
} 

EDIT: Según el comentario

Por defecto Entity Framework va a hacer una tabla Por Jerarquía .Todas de datos en la jerarquía se guarda en un único tabla y utiliza la columna Discriminator para identificar qué registro pertenece a qué subtipo. Entonces, como resultado, tendrá una tabla de Vehículos con columnas igual a las propiedades de Todas sus clases en la jerarquía con una columna adicional llamada "Discriminator". Para un Record para automóvil, tendrá el valor "Car" dentro de la columna Discriminator.

enter image description here

Si desea crear la tabla individual por cada tipo, vamos a ir a por tabla según el tipo de. Entity Framework creará una tabla para la clase base y una tabla separada para todas las clases secundarias.

Para que esto suceda, puede usar la API Fluent para anular la configuración.

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<Car>().ToTable("Cars"); 
     modelBuilder.Entity<Motorcycle>().ToTable("Motorcycles"); 

     base.OnModelCreating(modelBuilder); 
    } 

Y la salida es

enter image description here

Ahora usted debería ser capaz de consultar las entradas de vehículos como éste

var vehicles = dbContext.Set<Vehicle>().Where(x => x.TopSpeed > 150).ToList(); 

Y el resultado es que aquí

enter image description here

Observe que el resultado contiene el tipo MotorCycle y el tipo Car.

Compruebe esto link para decidir qué estrategia de herencia usar.

+0

Correcto. Olvidé incluir el id id en mi ejemplo. –

+0

Intenté esto y combinó mis autos y motos en una mesa llamada vehículos. Quiero una tabla por tipo. –

+0

@ByronSommardahl: ver mi respuesta actualizada. – Shyju

0

¿Ha intentado darle al Vehículo su propio contexto con solo un DBSet? Creo que eso podría hacerlo por ti.

+0

La consulta funciona cuando hago esto, pero las tablas se rompen en una sola. Antes era tabla por tipo ... no es tabla por jerarquía. –

+0

Entonces, para que quede claro que tiene un VehicleDbContext y un MyDbContext (con autos y moto), ¿todavía crea una tabla llamada Vehicle? ¿Qué estás usando para crear las tablas? Además, ¿ha intentado usar el escritor EDMX para asegurarse de que la herencia es exactamente como lo planeó? –

0

Al utilizar una entrada DataAnnotation.Schema.Table ("TableName"), en la clase heredada, se inicia la creación de una nueva tabla para el tipo heredado (tabla por tipo) y se elimina el campo discriminador en el tipo principal tabla, sin la necesidad del código Fluent API.

Cuestiones relacionadas