Prueba mi solución . Se evita la generación de migración para las tablas marcados como vistas
kogoia
Respuestas:
95
Si, como yo, está interesado solo en mapear entidades provenientes de otra base de datos (un erp en mi caso) para relacionarlas con entidades específicas de su aplicación, entonces puede usar las vistas como usa una tabla (mapee la vista en de la misma manera!). Obviamente, si intenta actualizar esas entidades, obtendrá una excepción si la vista no es actualizable. El procedimiento es el mismo que en el caso de las entidades normales (basadas en una tabla):
Cree una clase POCO para la vista; por ejemplo FooView
Agregue la propiedad DbSet en la clase DbContext
Use un archivo FooViewConfiguration para establecer un nombre diferente para la vista (usando ToTable ("Foo"); en el constructor) o para establecer propiedades particulares
+1 por no asumir que "Code First" == generación automática de base de datos
onetwopunch
3
@DaveJellison, ¿le importaría detallar o proporcionar un enlace sobre cómo agregar una vista como parte de un IDatabaseInitializer?
Ralph Shillington
18
¿Soy solo yo o todo el mundo está obteniendo una tabla vacía creada por la migración? ¿Hay alguna forma de evitarlo?
Kremena Lalova
4
Solo asegurándome aquí, ¿esta solución requiere que creemos una Vista en la base de datos SQL de antemano externamente? ¿Es posible definir la vista en el código y hacer que se complete en la base de datos a través del comando Agregar-Migración / Actualizar-Base de datos?
frostshoxx
6
Unas pocas cosas. 1. Esta respuesta no menciona que debe crear la vista manualmente usando SQL, esto se puede hacer usando una migración. 2. No es necesario que configure el nombre de la vista si el nombre de la clase coincide con el nombre de la vista. 3. Puede usar DataAnnotations de esta manera:, [Table("myView")]esto es posiblemente más simple que usar la creación de un EntityTypeConfiguration.
Rudey
23
Esto puede ser una actualización, pero para usar vistas con EF Code primero, simplemente agregue [Table ("NameOfView")] a la parte superior de la clase y todo debería funcionar bien sin tener que pasar por todos los obstáculos por los que están pasando los demás. Además, deberá informar una de las columnas como una columna [clave]. Aquí está mi código de muestra a continuación para implementarlo.
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespaceSomeProject.Data
{
[Table("SomeView")]
publicclassSomeView
{
[Key]
publicint NameID { get; set; }
publicstring Name { get; set; }
}
}
Y así es como se ve el contexto
using System.Data.Entity;
namespaceSomeProject.Data
{
publicclassDatabaseContext : DbContext
{
public DbSet<SomeView> SomeViews { get; set; }
}
}
Esta es la misma que la respuesta aceptada, excepto que usa DataAnnotations mientras que la respuesta aceptada usa EF Fluid API.
Rudey
4
En realidad, no, no lo es. Intenté, sin éxito, la respuesta aceptada y no funcionó bien para mí. Pero luego estoy usando Migraciones, por lo que esto puede haber afectado las cosas. Descubrí que primero tenía que hacer mis migraciones, LUEGO agregar mi clase de vista ya que ya existía en la base de datos. Lo manejaríamos exactamente de la misma manera si ya tuviéramos tablas existentes en la base de datos. Dado que una vista es una "tabla virtual", la sintaxis de la tabla en Entity Framework todavía funciona.
Charles Owen
11
Si todo lo que desea es un montón de objetos desnormalizados, entonces podría crear una IQueryable<TDenormolized>propiedad pública de solo obtención en su DbContextclase.
En el get, devuelve un resultado de Linq para proyectar los valores desnormoalizados en sus objetos desnormalizados. Esto podría ser mejor que escribir una vista de base de datos porque está programando, no está limitado solo por usar selectdeclaraciones. También es seguro en tiempo de compilación.
Solo tenga cuidado de no activar enumeraciones como ToList()llamadas, que romperán la consulta diferida y puede terminar obteniendo un millón de registros de la base de datos y filtrarlos en su servidor de aplicaciones.
No sé si esta es la forma correcta, pero lo intenté y me funciona.
Una de las razones por las que me gustaría usar vistas es que el SQL generado por EF no siempre es 'bueno': tenemos algunas jerarquías de herencia en nuestro modelo (descubrí las trampas demasiado tarde ...) y el uso de vistas nos permite para crear manualmente el SQL. Solo un contrapunto de por qué sería preferible una vista
Carl
2
Otra razón para no hacer esto podría ser el uso de expresiones de tabla comunes recursivas, que no están disponibles en LINQ. Pero por lo demás, este es un buen consejo para escenarios más simples.
Tom Pažourek
1
Usar una propiedad en lugar de una vista no es una opción si desea aprovechar los beneficios de una vista indexada .
Rudey
"no está limitado por utilizar únicamente sentencias de selección". ¿Qué quiere decir con esto? Todo lo que pueda hacer con LINQ se puede hacer usando sentencias SELECT, no se puede decir lo mismo al revés.
Rudey
3
Sé que esta es una pregunta antigua y hay muchas respuestas aquí, pero me vi obligado a tener un problema cuando uso esta respuesta y se produjo un error cuando uso el comando update-database en la Consola del Administrador de paquetes:
Ya existe un objeto llamado '...' en la base de datos.
y utilizo estos pasos para resolver este problema:
ejecute este comando en la consola del administrador de paquetes: Add-migration intial
En la carpeta Migraciones, puede encontrar el archivo ..._ intial.cs, abrirlo y comentar o eliminar cualquier comando relacionado con su clase que desee asignar
ahora normalmente puede usar el comando update-database para cualquier otro cambio en sus modelos
¡Gracias! ¡Esto realmente ayudó! Como extra, en lugar de simplemente eliminar el código generado con EF Migrations, puede agregar allí migrationBuilder.Sql("CREATE OR REPLACE VIEW ...); Para que los colegas también puedan usarlo para actualizar su base de datos.
Respuestas:
Si, como yo, está interesado solo en mapear entidades provenientes de otra base de datos (un erp en mi caso) para relacionarlas con entidades específicas de su aplicación, entonces puede usar las vistas como usa una tabla (mapee la vista en de la misma manera!). Obviamente, si intenta actualizar esas entidades, obtendrá una excepción si la vista no es actualizable. El procedimiento es el mismo que en el caso de las entidades normales (basadas en una tabla):
Use un archivo FooViewConfiguration para establecer un nombre diferente para la vista (usando ToTable ("Foo"); en el constructor) o para establecer propiedades particulares
public class FooViewConfiguration : EntityTypeConfiguration<FooView> { public FooViewConfiguration() { this.HasKey(t => t.Id); this.ToTable("myView"); } }
Agregue el archivo FooViewConfiguration al modelBuilder, por ejemplo, anulando el método OnModelCreating del contexto:
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new FooViewConfiguration ()); }
fuente
[Table("myView")]
esto es posiblemente más simple que usar la creación de unEntityTypeConfiguration
.Esto puede ser una actualización, pero para usar vistas con EF Code primero, simplemente agregue [Table ("NameOfView")] a la parte superior de la clase y todo debería funcionar bien sin tener que pasar por todos los obstáculos por los que están pasando los demás. Además, deberá informar una de las columnas como una columna [clave]. Aquí está mi código de muestra a continuación para implementarlo.
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace SomeProject.Data { [Table("SomeView")] public class SomeView { [Key] public int NameID { get; set; } public string Name { get; set; } } }
Y así es como se ve el contexto
using System.Data.Entity; namespace SomeProject.Data { public class DatabaseContext : DbContext { public DbSet<SomeView> SomeViews { get; set; } } }
fuente
Si todo lo que desea es un montón de objetos desnormalizados, entonces podría crear una
IQueryable<TDenormolized>
propiedad pública de solo obtención en suDbContext
clase.En el
get
, devuelve un resultado de Linq para proyectar los valores desnormoalizados en sus objetos desnormalizados. Esto podría ser mejor que escribir una vista de base de datos porque está programando, no está limitado solo por usarselect
declaraciones. También es seguro en tiempo de compilación.Solo tenga cuidado de no activar enumeraciones como
ToList()
llamadas, que romperán la consulta diferida y puede terminar obteniendo un millón de registros de la base de datos y filtrarlos en su servidor de aplicaciones.No sé si esta es la forma correcta, pero lo intenté y me funciona.
fuente
Sé que esta es una pregunta antigua y hay muchas respuestas aquí, pero me vi obligado a tener un problema cuando uso esta respuesta y se produjo un error cuando uso el comando update-database en la Consola del Administrador de paquetes:
y utilizo estos pasos para resolver este problema:
Espero eso ayude.
fuente
migrationBuilder.Sql("CREATE OR REPLACE VIEW ...
); Para que los colegas también puedan usarlo para actualizar su base de datos.