Entity Framework Core

Entity Framework (EF) es un ORM que trabaja con la base de datos (BD) de forma desconectada. Esto quiere decir que EF no sabe en ningún momento que datos hay en la BD si previamente no he hecho una consulta para recuperarlos.

Por ejemplo para borrar un cierto objeto de BD a partir del Id, el código sería algo así:

var user = db.Users.Find(id);
db.Users.Remove(user);
db.SaveChanges();

Por ejemplo para borrar un cierto objeto de BD a partir del Id, el código sería algo así:

var user = db.Users.Find(id);
db.Users.Remove(user);
db.SaveChanges();

Si el objeto user no se obtiene de la BD si no que lo creamos en memoria, EF no lo borraría ya que no tiene conocimiento si este objeto existe en BD.

// esto no funciona, no borra el user
var user = new User() { Id = id};
db.Users.Remove(user);
db.SaveChanges();

Si por algún motivo queremos trabajar de forma desconectada (hay que tener cuidado), tenemos que indicarle a EF de alguna manera que ese objeto existe. Esto se hace mediante attatch.

var user = new User() { Id = id};
db.Users.Attach(user);
db.Users.Remove(user);
db.SaveChanges();

El método de EF saveChanges sincroniza todo lo que haya en memoria con la BD. Este método es transaccional, es decir si hay varios cambios en memoria y uno peta, no se aplicará ninguno. Se hará un rollback de la BD y se quedará en el estado anteior.

Herramienta de línea de comandos para Entity Framework Core (dotnet-ef)

Instalar globalmente

> dotnet tool install dotnet-ef -g

Actualizar de forma global

> dotnet tool update --global dotnet-ef

Crear migracion con dotnet-ef

Instalar paquete de Nuget necesario

> dotnet add package Microsoft.EntityFrameworkCore.Design

Crear migración inicial

> cd myProject
> dotnet ef migrations add Initial

Aplicar la migración a la base de datos

> dotnet ef database update

Uso de Linq

Hay expresiones que no son válidas en Linq para EF. Por ejemplo, en un Where no se puede llamar a una función.

// Esto no funciona. EF no sabe resolver GetCleanName
db.Users.Where(u => GetCleanName(u.Name) == name).ToList();

// Esto si funciona
var cleanName = GetCleanName(u.Name);
db.Users.Where(u => cleanName == name).ToList();

Model first

http://www.entityframeworktutorial.net/efcore/entity-framework-core-console-application.aspx

Pasos:

  • Crear modelo
  • Crear schema
  • Crear migración
  • add-migration CreateSchoolDB -project XXX
  • Crear BD
  • update-database –verbose

Creación del modelo

Para la creación del modelo hay que definir una clase que represente el contexto y sus entidades. Esta clase hereda de DbContext y sus entidades se definen mediante DbSet.

Ejemplo:

using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;

namespace EFGetStarted
{
    public class BloggingContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
        public DbSet<Post> Posts { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder options)
            => options.UseSqlite("Data Source=blogging.db");
    }

    public class Blog
    {
        public int BlogId { get; set; }
        public string Url { get; set; }

        public List<Post> Posts { get; } = new List<Post>();
    }

    public class Post
    {
        public int PostId { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }

        public int BlogId { get; set; }
        public Blog Blog { get; set; }
    }
}

En el ejemplo anterior se está utilizando una base de datos SQLite. En el método OnConfiguring se está definiendo su cadena de conexión. Esto es a modo de ejemplo, no es una buena práctica colocar en el código la cadena de conexión ya que estamos exponiendo las credenciales.

Tampoco es buena práctica definir las clases de entidad Blog y Post en el mismo archivo. Estas irían cada uno en un archivo independiente.

Crear modelos a partir de BD existente (scaffold)

Powershell

> Scaffold-DbContext "...connection string" Microsoft.EntityFrameworkCore.SqlServer -Context "ExampleContext" -Project ExampleBusinessLogic -Tables "table1","table2", "tableN" 

Dotnet

dotnet ef dbcontext scaffold "Server=(localdb)\mssqllocaldb;Database=Resources;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -o ../ResourcesBusinessLogic/Data/ -t Subscriptions --context-dir ../ResourcesBusinessLogic/Data/ -c ResourcesContext 

Se crean los modelos para las tablas seleccionadas (-t) y se crea el contexto en una carpeta independiente con un nombre y un espacio de nombres especificados.

Crear una migración

PMC (Consola de Administración de Paquetes – Powershell)

> Add-Migration Initial -project UserBusinessLogic -StartupProject UserBusinessLogic
> Add-Migration AddPasswordToUsuarios -project UserBusinessLogic -StartupProject UserBusinessLogic
> Add-Migration Initial --context BlogContext -project AccountancyBusinessLogic

CLI (Herramienta de la Interfaz de la línea de Comandos)

dotnet ef --version
dotnet ef migrations add InitialCreate --project UserBusinessLogic --startup-project UsersAPI
dotnet ef database update --context BlogContext --project UserBusinessLogic --startup-project UsersAPI

--project: indica el proyecto donde se crearán los archivos de migración (por defecto es el directorio bajo el cual se ejecuta el comando)

--startup-project: proyecto de inicio donde se compila y ejecutan los comandos. Es el que indica la cadena de conexión a BD.

--context: especifica el contexto sobre el que aplicar la migración. Necesario en el caso de que exista más de uno.

--verbose: muestra el log del proceso

Deshacer una migración

CLI

dotnet ef migrations remove
dotnet ef database update PreviousMigration --project UserBusinessLogic --startup-project UsersAPI

Eliminar migración (powershell) 

> Remove-Migration -project XXX

Asignar propiedades de auditoría

Reemplazar el método saveChanges para asignar de forma automática las propiedades de auditoria (created_at, created_by…)

Crear base de datos SQLite

SQLite es un sistema de gestión de base de datos relacional. Esta no requiere de servidor para su funcionamiento ya que se almacena en un archivo y se comunica directamente con la aplicación embebiéndose en ella.

Se suele utilizar para aplicaciones pequeñas que no requieran muchos accesos simultáneos a base de datos.

La versión 3 de SQLite permite bases de datos de hasta 2 Terabytes de tamaño y la inclusión de campos tipo BLOB.

Crearemos la base de datos mediante los comandos de dotnet. Usaremos el sistema de migraciones creando una migración inicial que nos genere la base de datos.

Ver cómo crear una migración.

👇Tu comentario