INDICE
¿Qué es Code-First?
Instalar Entity Framework
Ejemplo simple de Code-First
Convenciones de Code-First
Inicialización de base de datos
Estrategia de inicialización de base de datos
Estrategia de herencia
Configurar clases de dominio
Atributos de anotaciones de datos
Taba
Columna
Clave
NotMapped
Foreing Key
Index
InverseProperty
Requerido
Longitud máxima
Longitud de la cuerda
TimeStamp
Base de datos generada
ConcurrencyCheck
API fluida
Asignaciones de entidades
Asignaciones de propiedades
Configurar uno a uno
Configurar uno a varios
Configurar varios a varios
Desde la base de datos existente
Eliminar en cascada
Asignación de procedimientos almacenados
Mover configuraciones
Datos de semillas
Convenciones personalizadas
Migración
Migración automatizada
Migración basada en código
EF Herramientas eléctricas
1. ¿Qué es Code-First?
Entity Framework introdujo el enfoque Code-First con Entity Framework 4.1. Code-
First es principalmente útil en el diseño controlado por dominios. En el enfoque Code-
First, usted se enfoca en el dominio de su aplicación y comienza a crear clases para su
entidad de dominio en lugar de diseñar su base de datos primero y luego crear las
clases que coincidan con el diseño de su base de datos. La siguiente figura ilustra el
enfoque de código primero.
Como puede ver en la figura anterior, EF API creará la base de datos en función de las
clases y la configuración de su dominio. Esto significa que primero debe comenzar a
codificar en C # o [Link] y luego EF creará la base de datos a partir de su código.
Flujo de trabajo de Code-First
La siguiente figura ilustra el flujo de trabajo de desarrollo de código primero.
El flujo de trabajo de desarrollo en el enfoque de código primero sería: Crear o
modificar clases de dominio -> configurar estas clases de dominio usando Fluent-API o
atributos de anotación de datos -> Crear o actualizar el esquema de base de datos
usando migración automatizada o migración basada en código.
Instalar Entity Framework 6
Debe instalar [Link] (EF API) en su proyecto en Visual Studio para
trabajar con el enfoque Code-First.
Aquí, instalaremos Entity Framework 6 API usando NuGet Package Manager en Visual
Studio. (Puede instalar EF a través de NuGet de la misma manera en cualquier versión
de Visual Studio).
Haga clic con el botón derecho en su proyecto en el explorador de soluciones y
seleccione Administrar paquetes NuGet.
Esto abrirá el cuadro de diálogo Administrar paquetes NuGet. Busque EntityFramework
en el cuadro de búsqueda superior izquierdo y presione Entrar. Mostrará todas las
API / complementos comenzando con EntityFramework como se muestra a
continuación.
Seleccione EntityFramework (asegúrese de que el autor sea Microsoft y la versión sea
6.x) y haga clic en Instalar. Esto abrirá el cuadro de vista previa como se muestra a
continuación. Revise los cambios y haga clic en Aceptar.
Nuevamente, haga clic en el botón Acepto en el cuadro de diálogo Aceptación de
licencia para iniciar la instalación.
Esto instalará la API de Entity Framework en el proyecto.
Después de la instalación, asegúrese de que la versión adecuada de
[Link] esté incluida en el proyecto.
Ahora, estamos listos para usar Entity Framework en nuestro proyecto. Creemos
nuestro primer ejemplo de código simple en el próximo capítulo.
2. Ejemplo simple de Code-First
En el capítulo anterior, instalamos el marco de entidad en nuestro proyecto. Aquí, crearemos
un ejemplo de código simple.
Supongamos que queremos crear una aplicación simple para XYZ School. Los usuarios de esta
aplicación de la escuela deben poder agregar y actualizar la información de los estudiantes, las
calificaciones, los maestros y los cursos.
En lugar de diseñar tablas de base de datos primero, comencemos a crear clases para nuestro
dominio escolar, cuando sea necesario. Primero, cree las clases de Alumno y Grado donde
cada Alumno está asociado con un Grado como se muestra a continuación. A esto se le llama
relación de uno a varios. Obtenga información sobre cómo EF administra la relación entre
entidades (clases de dominio) aquí.
Cree la clase de Grado (Grade) como se muestra a continuación.
Ahora, hemos terminado con las clases de dominio iniciales para nuestra aplicación escolar.
El enfoque Code-First también requiere una clase de contexto que debe derivarse de la clase
DbContext. Cree una clase de contexto como se muestra a continuación. Se deriva de la clase
DBContext y expone las propiedades de DbSet para los tipos que desea que formen parte del
modelo, p. Ej. Clases de estudiante y grado en este caso. El DbSet es una colección de clases de
entidad (también conocido como conjunto de entidad), por lo que le hemos dado el nombre
de la propiedad como el plural del nombre de la entidad como Estudiantes y Grados.
Ahora, hemos terminado con las clases requeridas para el enfoque de Code-First. Ahora
agregaremos un estudiante usando la clase de contexto como se muestra a continuación.
Si ejecuta la aplicación, verá que un estudiante se insertó correctamente en la base de datos.
Pero, ¿Dónde está la base de datos y cuáles son las tablas y sus columnas?
Ésta es la belleza de EF Code-First API. Crea la base de datos basada en el parámetro pasado en
el constructor base de su clase de contexto. Como no hemos pasado ningún parámetro en el
constructor de nuestra clase de contexto, creó la base de datos [Link] en
la base de datos local SQLEXPRESS, como se muestra a continuación. También creó dos tablas
en esta base de datos, Estudiantes y Calificaciones basadas en las clases de dominio Estudiante
y Grado definidos anteriormente.
Como puede ver en la figura anterior, ha creado tablas de Estudiantes y Calificaciones y cada
tabla contiene columnas con el tipo de datos y la longitud adecuados. Los nombres de las
columnas y el tipo de datos coinciden con las propiedades de las respectivas clases de dominio.
También ha convertido StudentId y GradeId como PK (claves principales) y ha creado la
columna Grade_GradeId como FK (clave externa).
De esta manera, sin crear primero una base de datos, puede comenzar a escribir una
aplicación que eventualmente creará una base de datos a partir de sus clases de dominio.
Nota: Si modifica estas clases y ejecuta la aplicación nuevamente, generará la siguiente
excepción.
Debe definir la estrategia de inicialización de la base de datos en la clase de contexto para
modificar las clases de dominio y ejecutar la aplicación localmente. Infórmese aquí. Debe
preguntarse cómo ha creado columnas con los tipos de datos y la longitud adecuados con PK y
FK, ¿verdad? La respuesta es usar convenciones de código primero. Aprenda las convenciones
de código primero en la siguiente sección.
3. Convenciones de EF 6 Code-First
Las convenciones son conjuntos de reglas predeterminadas que configuran automáticamente
un modelo conceptual basado en sus clases de dominio cuando se trabaja con el enfoque
Code-First. Como ha visto en el ejemplo de código primero en el capítulo anterior, EF API
configuró PrimaryKeys, ForeignKeys, relaciones, tipos de datos de columna, etc. de las clases
de dominio sin ninguna configuración adicional. Esto se debe a las convenciones de código EF
primero. Si se siguen en las clases de dominio, el esquema de la base de datos se configurará
según las convenciones. Estas convenciones de EF 6.x Code-First se definen en el espacio de
nombres [Link].
La siguiente tabla enumera las primeras convenciones del código predeterminado:
CONVENCIÓN PREDETERMINADA PARA DESCRIPCIÓN
Schema De forma predeterminada, EF crea todos los
objetos DB en el esquema dbo.
Table Name <Nombre de clase de entidad> + 's'
EF creará una tabla de base de datos con el
nombre de la clase de entidad con el sufijo
's', p. Ej. La clase (entidad) de dominio de
estudiante se asignaría a la tabla de
Estudiantes.
Primary key Name 1) Identificación
2) <Nombre de clase de entidad> + "Id" (no
distingue entre mayúsculas y minúsculas)
EF creará una columna de clave principal
para la propiedad denominada Id o
<Nombre de clase de entidad> + "Id" (no
distingue entre mayúsculas y minúsculas
Foreign key property Name De forma predeterminada, EF buscará la
propiedad de clave externa con el mismo
nombre que el nombre de clave principal de
la entidad principal. Si la propiedad de clave
externa no existe, EF creará una columna FK
en la tabla Db con <Nombre de propiedad de
navegación dependiente> + "_" + <Nombre
de propiedad de clave principal de la entidad
principal> [Link]. EF creará la columna de clave
externa Grade_GradeId en la tabla
Estudiantes si la entidad Estudiante no
contiene la propiedad de clave externa para
Grade.
Null column EF crea una columna nula para todas las
propiedades de tipo de referencia y
propiedades primitivas que aceptan valores
NULL, p. string, Nullable <int>, Student,
Grade (todas las propiedades de tipo de
clase)
Not Null Column EF crea columnas NotNull para propiedades
de clave principal y propiedades de tipo de
valor no anulables, p. Ej. int, float, decimal,
datetime, etc.
DB Columns order EF creará columnas de base de datos en el
mismo orden que las propiedades en una
clase de entidad. Sin embargo, las columnas
de clave principal se moverían primero.
Properties mapping to DB De forma predeterminada, todas las
propiedades se asignarán a la base de datos.
Utilice el atributo [NotMapped] para excluir
la propiedad o la clase del mapeo de la base
de datos.
Cascade delete Habilitado de forma predeterminada para
todo tipo de relaciones.
La siguiente tabla enumera el tipo de datos de C # asignado con el tipo de datos de SQL Server.
TIPO DE DATOS C # ASIGNACIÓN AL TIPO DE DATOS DE SQL SERVER
int int
string nvarchar(max)
decimal decimal(18,2)
float real
byte[] varbinary(max)
datetime datetime
bool bit
byte tinyint
short smallint
long bigint
doublé float
char no mapping
sbyte no mapping (throws exception)
object no mapping
La siguiente figura ilustra el mapeo de convenciones con la base de datos.
Convención de relaciones
EF 6 infiere la relación uno a varios mediante la propiedad de navegación de forma
predeterminada. Visite el capítulo Convención para la relación de uno a varios para obtener
más información.
Nota: EF 6 no incluye las convenciones predeterminadas para las relaciones uno a uno y varios
a varios. Debe configurarlos mediante Fluent API o DataAnnotation.
Convención de tipo complejo
Code-First crea el tipo complejo para la clase que no incluye la propiedad de la clave y además
la clave principal no se registra mediante el atributo de anotación de datos o la API Fluent.
Esta fue una descripción general de las primeras convenciones del código. Estas convenciones
se pueden anular mediante DataAnnotation o Fluent API.
4. Database Initialization in Entity Framework 6
Hemos visto que Code-First crea una base de datos automáticamente en la sección Ejemplo de
código simple primero. Aquí, aprenderemos cómo EF decide el nombre de la base de datos y el
servidor mientras inicializa una base de datos en el enfoque de código primero.
La siguiente figura muestra un flujo de trabajo de inicialización de base de datos, basado en el
parámetro pasado en el constructor base de la clase de contexto, que se deriva de DbContext:
Según la figura anterior, el constructor base de la clase de contexto puede tener el siguiente
parámetro.
1) Sin parámetro
2) Nombre de la base de datos
3) Nombre de la cadena de conexión
Sin parámetro
Si no especifica el parámetro en el constructor base de la clase de contexto, entonces crea una
base de datos en su servidor SQLEXPRESS local con un nombre que coincide con su {Espacio de
nombres}. {Nombre de clase de contexto}. Por ejemplo, EF creará una base de datos llamada
[Link] para la siguiente clase de contexto:
Nombre de la Base de datos
También puede especificar el nombre de la base de datos como parámetro en un constructor
base de la clase de contexto. Si especifica un parámetro de nombre de base de datos, Code
First crea una base de datos con el nombre que especificó en el constructor base en el servidor
de base de datos local SQLEXPRESS. Por ejemplo, Code First creará una base de datos llamada
MySchoolDB para la siguiente clase de contexto.
Nombre de la cadena de conexión
También puede definir la cadena de conexión en [Link] o [Link] y especificar el
nombre de la cadena de conexión comenzando con "name =" en el constructor base de la clase
de contexto. Considere el siguiente ejemplo donde pasamos el parámetro name =
SchoolDBConnectionString en el constructor base.
[Link]:
En la clase de contexto anterior, especificamos un nombre de cadena de conexión como
parámetro. Tenga en cuenta que el nombre de la cadena de conexión debe comenzar con
"name =", de lo contrario lo considerará como un nombre de base de datos. El nombre de la
base de datos en la cadena de conexión en [Link] es SchoolDB-ByConnectionString. EF
creará una nueva base de datos SchoolDB-ByConnectionString o utilizará la base de datos
SchoolDB-ByConnectionString existente en el servidor SQL local. Asegúrese de incluir
providerName = "[Link]" para la base de datos de SQL Server en la cadena de
conexión.
5. Estrategias de inicialización de base de datos en EF 6 Code-
First
Ya creó una base de datos después de ejecutar su aplicación Code-First la primera vez, pero
¿qué pasa con la segunda vez en adelante? ¿Creará una nueva base de datos cada vez que
ejecute la aplicación? ¿Qué pasa con el entorno de producción? ¿Cómo modificas la base de
datos cuando cambias tu modelo de dominio? Para manejar estos escenarios, debe utilizar una
de las estrategias de inicialización de la base de datos.
Hay cuatro estrategias diferentes de inicialización de bases de datos:
1) CreateDatabaseIfNotExists: este es el inicializador predeterminado. Como sugiere el
nombre, creará la base de datos si no existe ninguna según la configuración. Sin
embargo, si cambia la clase de modelo y luego ejecuta la aplicación con este
inicializador, generará una excepción.
2) DropCreateDatabaseIfModelChanges: este inicializador elimina una base de datos
existente y crea una nueva base de datos, si sus clases de modelo (clases de entidad)
se han modificado. Por lo tanto, no tiene que preocuparse por mantener el esquema
de su base de datos cuando cambian las clases de su modelo.
3) DropCreateDatabaseAlways: como sugiere el nombre, este inicializador elimina una
base de datos existente cada vez que ejecuta la aplicación, independientemente de si
sus clases de modelo han cambiado o no. Esto será útil cuando desee una base de
datos nueva cada vez que ejecute la aplicación, por ejemplo, cuando esté
desarrollando la aplicación.
4) Custom DB Initializer: también puede crear su propio inicializador personalizado, si lo
anterior no satisface sus requisitos o si desea realizar algún otro proceso que inicialice
la base de datos utilizando el inicializador anterior.
Para utilizar una de las estrategias de inicialización de base de datos anteriores, debe
configurar el inicializador de base de datos utilizando la clase de base de datos en una
clase de contexto, como se muestra a continuación:
También puede crear su inicializador de base de datos personalizado, heredando uno de
los inicializadores, como se muestra a continuación:
En el ejemplo anterior, SchoolDBInitializer es una clase de inicializador personalizada que
se deriva de CreateDatabaseIfNotExists. Esto separa el código de inicialización de la base
de datos de una clase de contexto.
Establecer el inicializador de base de datos en el archivo de configuración.
También puede configurar el inicializador db en el archivo de configuración. Por ejemplo,
para configurar el inicializador predeterminado en [Link]:
Puede configurar el inicializador de base de datos personalizado, de la siguiente manera:
Apague el DB Initializer
Puede desactivar el inicializador de la base de datos para su aplicación. Suponga que no
desea perder datos existentes en el entorno de producción, luego puede desactivar el
inicializador, como se muestra a continuación:
También puede desactivar el inicializador en el archivo de configuración, por ejemplo:
6. Estrategia de herencia en Entity Framework 6
Hemos visto en la sección Convenciones de Code-First que EF crea tablas de base de datos
para cada clase de dominio concreta. Sin embargo, puede diseñar sus clases de dominio
usando herencia. Las técnicas orientadas a objetos incluyen las relaciones "tiene un" y "es un",
mientras que el modelo relacional basado en SQL sólo tiene una relación "tiene un" entre
tablas. Los sistemas de administración de bases de datos SQL no admiten la herencia de tipos.
Entonces, ¿cómo mapearía las clases de dominio orientadas a objetos con la base de datos
relacional?
A continuación, se muestran tres enfoques diferentes para representar una jerarquía de
herencia en Code-First:
Tabla por jerarquía (TPH): este enfoque sugiere una tabla para toda la jerarquía de
herencia de clases. La tabla incluye una columna discriminadora que distingue entre clases
de herencia. Esta es una estrategia de asignación de herencia predeterminada en Entity
Framework.
Tabla por tipo (TPT): este enfoque sugiere una tabla separada para cada clase de dominio.
Tabla por clase concreta (TPC): este enfoque sugiere una tabla para una clase concreta,
pero no para la clase abstracta. Entonces, si hereda la clase abstracta en varias clases
concretas, las propiedades de la clase abstracta serán parte de cada tabla de la clase
concreta.
No vamos a entrar en detalles aquí. Visite los siguientes enlaces de referencia para obtener
información más detalladle:
1. Inheritance with EF Code First: Table per Hierarchy (TPH)
2. Inheritance with EF Code First: Table per Type (TPT)
3. Inheritance with EF Code First: Table per Concrete class (TPC)
7. Configurar clases de dominio en Entity Framework 6
Aprendimos las convenciones predeterminadas de Code-First en la sección anterior. Code-First
crea el modelo conceptual a partir de sus clases de dominio utilizando las convenciones
predeterminadas. EF 6 Code-First aprovecha un patrón de programación denominado
convención sobre configuración. Sin embargo, puede anular estas convenciones configurando
sus clases de dominio para proporcionar a EF la información que necesita. Hay dos formas de
configurar sus clases de dominio:
Atributos de anotación de datos
API fluida
Atributos de anotaciones de datos
Anotaciones de datos es una configuración basada en atributos simple, que puede aplicar a sus
clases de dominio y sus propiedades. Estos atributos no son solo para EF, sino que también se
usan en el formulario web [Link] o MVC y, por lo tanto, se incluyen en un espacio de
nombres separado [Link].