Entity Framework Core & Micro-Orms with Asp.Net Core

Preview:

Citation preview

ASPNET CORE DATA ACCESSENTITY FRAMEWORK CORE & MICRO ORMS

ETAT DES LIEUX : EF CORE 1.0

Nouvelles plateformes

.NET CORE (ASP.NET Core, UWP)

.NET Framework (ASP.NET, WPF, Windows Forms)

XAMARIN

Windows Phone

Windows Store

MAC

Linux

ETAT DES LIEUX : EF CORE 1.0

Nouvelles sources de données

Relationnelles (SQL Server, SQL Lite, SQL Compact, Postgres, MySQL, Oracle)

Non relationnelles (Redis, Azure Table Storage)

InMemory (à utiliser pour les test)

Providers disponibles uniquement pour les SGBD relationnels pour la v 1.0

Possibilité de créer son propre provider

ENTITY FRAMEWORK CORE 1.0

On repart de Zero mais on garde le meilleur

Code First

Code First from Database

Approche totalement modulaire

IOC friendly

Totalement Open source comme tout ce qui finit par Core… donc code source disponible sur GitHub et possiblité de contribuer son l’évolution.

EF Core n’est pas production ready

ENTITY FRAMEWORK CORE 1.0

Fonctionnalités legacy

Change tracking

Migrations

DbContext API

Linq to Entities

SaveChanges

Fonctionnalités supprimées

EDMX

Entity SQL

Complex Mapping

Migrations automatiques

ENTITY FRAMEWORK CORE 1.0

Nouvelles fonctionnalités

Dependency injection

Lancer des Batch avec CUD

Créer des clé étrangères

SQL généré plus propre et plus light

Amélioration des graphes d’objets déconnectés

Fonctionnalités à venir

Mapping des procédures stockées

Lazy loading

ENTITY FRAMEWORK CORE 1.0.1DEMARRAGE

ENTITY FRAMEWORK CORE 1.0

Package à installer

"Microsoft.EntityFrameworkCore.SqlServer": "1.0.1 "

Création d’un DbContext

public class CookBookContext : DbContext{

public CookBookContext(DbContextOptions<CookBookContext> options) : base(options) { }

public DbSet<Book> Book { get; set; }public DbSet<Recipe> Recipe { get; set; }

}

ENTITY FRAMEWORK CORE 1.0

Config dans appsettings.json

{"ConnectionStrings": {

"DbConnection": "Data Source=mcnltp173;Initial Catalog=CookBook;Integrated Security=True" }

}

Config dans Startup.cs

public void ConfigureServices(IServiceCollection services){

services.AddDbContext<CookBookContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DbConnection")));

}

ENTITY FRAMEWORK CORE 1.0

Utilisation

public class HomeController : Controller{

private readonly CookBookContext _context;public HomeController(CookBookContext context){

_context = context;}

public IActionResult Index(){

var books = _context.Book.ToList();return View(books);

}}

ENTITY FRAMEWORK CORE 1.0.1REVERSE ENGINEERING

ENTITY FRAMEWORK CORE 1.0

Command

dotnet ef dbcontext scaffold -c DbContextName -o ModelsFolder "MyConnectionString" Microsoft.EntityFrameworkCore.SqlServer –force

Config dans project.json

"dependencies": {"Microsoft.EntityFrameworkCore.SqlServer": "1.0.1",

"Microsoft.EntityFrameworkCore.SqlServer.Design": "1.0.1","Microsoft.EntityFrameworkCore.Design": "1.0.0-preview2-final"

},"tools": {

"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final" }

ENTITY FRAMEWORK CORE 1.0

Code généré

public partial class CookBookContext : DbContext{

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){

optionsBuilder.UseSqlServer(@"Data Source=mcnltp173;Initial Catalog=CookBook;Integrated Security=True");

}

protected override void OnModelCreating(ModelBuilder modelBuilder){

modelBuilder.Entity<Book>(entity =>{

entity.Property(e => e.Name).IsRequired().HasColumnType("varchar(50)");

});

}

public virtual DbSet<Book> Book { get; set; }public virtual DbSet<Recipe> Recipe { get; set; }

}

MICRO ORMSDAPPER - PETAPOCO - MASSIVE - SIMPLE.DATA - SERVICESTACK.ORMLITE

MICRO ORMS : DAPPER

POCO

DYNAMIC OBJECTS

MULTIPLE RESULTS

STORED PROCEDURE

TRANSACTION

ASYNC

PROVIDERS: SQLLite, SQL CE, Firebird, Oracle, MySQL, PostgreSQL and SQL Server

MICRO ORMS : DAPPER

CONFIG:public void ConfigureServices(IServiceCollection services){

services.Add(new ServiceDescriptor(typeof(IConfiguration),provider => new ConfigurationBuilder()

.SetBasePath(Directory.GetCurrentDirectory())

.AddJsonFile("appsettings.json",optional: false,reloadOnChange: true)

.Build(),ServiceLifetime.Singleton));

services.AddScoped<ICookBookRepository, CookBookRepository>();}// ou (v2) : public static IConfigurationRoot Configuration;public void ConfigureServices(IServiceCollection services){

services.AddScoped<ICookBookRepository, CookBookRepository>();}

MICRO ORMS : DAPPER

CTOR:private readonly IConfiguration _config;

public CookBookRepository(IConfiguration config){

_config = config;}public IDbConnection Connection{

get{

return new SqlConnection(_config.GetConnectionString("DbConnection"););}

}

// ou (v2) : public IDbConnection Connection{

get{

return new SqlConnection(Startup.Configuration["connectionStrings:DbConnection"]);}

MICRO ORMS : DAPPER

REPO:public IEnumerable<Book> GetAll(){

using (IDbConnection db = Connection){

db.Open();

// version requete Sqlreturn db.Query<Book>("SELECT * FROM Book").ToList<Book>;//return await db.QueryAsync<Book>("SELECT * FROM Book");

// version ps//return db.Query<Book>("GetAllBooks", commandType: CommandType.StoredProcedure);

}}

MICRO ORMS : DAPPER

public Book GetByID(int id){

using (IDbConnection db = Connection){

db.Open();

// version requete Sqlstring sQuery = "SELECT * FROM Book WHERE Id = @Id";return db.Query<Book>(sQuery, new { Id = id }).FirstOrDefault();

// version ps//string sp = "GetBookByID";//var parameter = new DynamicParameters();//parameter.Add("@Id", id, dbType: DbType.Int32, direction: ParameterDirection.Input);//return db.Query<Book>(sp, parameter, commandType: CommandType.StoredProcedure).FirstOrDefault();

}}

MICRO ORMS : DAPPER

public Book GetMultiple(int id){

using (IDbConnection db = Connection){

db.Open();// version requete Sql//string query = "SELECT * FROM Book WHERE Id=@id; SELECT * FROM Recipe WHERE IdBook=@id;";//var multipleResults = db.QueryMultiple(query, new { id = id });

// version spvar parameter = new DynamicParameters();parameter.Add("@id", id, dbType: DbType.Int32, direction: ParameterDirection.Input);var multipleResults = db.QueryMultiple("GetBookRecipes", parameter,

commandType: CommandType.StoredProcedure);

var book = multipleResults.Read<Book>().SingleOrDefault();var recipes = multipleResults.Read<Recipe>().ToList();if (book != null && recipes != null)

book.Recipes = new List<Recipe>(); book.Recipes.AddRange(recipes);return book;

}}

MICRO ORMS : DAPPER

public void Add(Book book){

using (IDbConnection db = Connection){

db.Open();var parameter = new DynamicParameters();parameter.Add("@name", book.Name, dbType: DbType.String, direction: ParameterDirection.Input);

//string sQuery = "INSERT INTO Book (Name) VALUES(@Name)";

// version 1 requete Sql//db.Execute(sQuery, parameter);

// version 2 requete Sql//db.Execute(sQuery, book);

// version spdb.Execute("InsertBook", parameter, commandType: CommandType.StoredProcedure);

}}

MICRO ORMS : DAPPER

public void Update(Book book){

using (IDbConnection db = Connection){

db.Open();var parameters = new DynamicParameters();parameters.Add("@Id", book.Id, dbType: DbType.Int32, direction: ParameterDirection.Input);parameters.Add("@Name", book.Name, dbType: DbType.String, direction: ParameterDirection.Input);

string sQuery = "UPDATE Book SET Name = @Name WHERE Id = @Id";

// version 1 requete Sql//db.Execute(sQuery, parameters, commandType: CommandType.Text);

// version 2 requete Sql//db.Execute(sQuery, book, commandType: CommandType.Text);

// version spdb.Execute("UpdateBook", parameters, commandType: CommandType.StoredProcedure);

}}

MICRO ORMS : DAPPER

public void Delete(int id){

using (IDbConnection db = Connection){

db.Open();// version 1 requete Sql//string sQuery = "DELETE FROM Book WHERE Id = @Id";//db.Execute(sQuery, new { Id = id });

// version spvar parameter = new DynamicParameters();parameter.Add("@Id", id, dbType: DbType.Int32, direction: ParameterDirection.Input);string sp = "DeleteBook";db.Execute(sp, parameter, commandType: CommandType.StoredProcedure);

}}

MICRO ORMS : PETAPOCO

POCO

DYNAMIC OBJECTS MAPPING

MULTIPLE RESULTS

STORED PROCEDURE

TRANSACTION

ASYNC

T4

PROVIDERS: SQL Server, SQL Server CE, MS Access, SQLite, MySQL, MariaDB, PostgreSQL, Firebird DB, and Oracle

APP.CONFIG

MICRO ORMS : PETAPOCO

CONFIG:public void ConfigureServices(IServiceCollection services){

services.AddScoped<ICookBookRepository, CookBookRepository>();}

CTOR:private readonly Database _db;

public CookBookRepository(){

var connectionString = ConfigurationManager.ConnectionStrings["DbConnection"].ConnectionString;_db = new Database(connectionString, new SqlServerDatabaseProvider());

}

MICRO ORMS : PETAPOCO

REPO:public IEnumerable<Book> GetAll(){

using (IDatabase dbConnection = Connection){

return _db.Query<Book>("SELECT * FROM Book");}

}

public Book GetByID(int id){

using (IDatabase dbConnection = Connection){

return _db.FirstOrDefault<Book>($"SELECT * FROM Book WHERE Id={id}");}

}

MICRO ORMS : PETAPOCO

public void Add(Book book){

using (IDatabase dbConnection = Connection){

_db.Insert(book);}

}

public void Update(Book book){

using (IDatabase dbConnection = Connection){

_db.Update(book);}

}

public void Delete(Book book){

using (IDatabase dbConnection = Connection){

_db.Delete(book);}

}

MICRO ORMS : MASSIVE

DYNAMIC OBJECTS

MULTIPLE RESULTS

STORED PROCEDURE

TRANSACTION

ASYNC

PROVIDERS: SQL Server, Oracle, SQLite, PostgreSQL

APP.CONFIG

MICRO ORMS : MASSIVE

CONFIG:public void ConfigureServices(IServiceCollection services){

services.AddScoped<ICookBookRepository, CookBookRepository>();}

public class Book : DynamicModel{

public Book():base("DbConnection", "Book","Id") { }

public int Id { get; set; }public string Name { get; set; }

}

MICRO ORMS : MASSIVE

REPO:public async Task<IList<dynamic>> GetAll(){

return await table.AllAsync();}

public async Task<dynamic> GetByID(int id){

return await table.SingleAsync($"WHERE Id={id}");}

MICRO ORMS : MASSIVE

public async Task Add(dynamic book){

await table.InsertAsync(book);}

public async Task Update(dynamic book){

await table.UpdateAsync(book, book.Id);}

public async Task Delete(int id){

await table.DeleteAsync(id);}

MICRO ORMS : SIMPLE.DATA

POCO

DYNAMIC OBJECTS

MULTIPLE RESULTS

STORED PROCEDURE

TRANSACTION

ASYNC

PROVIDERS: SQL Server, SQL Azure, SQL Server Compact, Oracle, MySQL, SQLite, PostgreSQL, SQLAnywhere, Informix, MongoDB, OData

MICRO ORMS : SIMPLE.DATA

CONFIG:public Startup(IHostingEnvironment env){

var builder = new ConfigurationBuilder().SetBasePath(env.ContentRootPath).AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);

Configuration = builder.Build();}public static IConfigurationRoot Configuration;

public void ConfigureServices(IServiceCollection services){

services.AddScoped<ICookBookRepository, CookBookRepository>()}

CTOR:private readonly dynamic _db;

public CookBookRepository(){

_db = Database.OpenConnection(Startup.Configuration["connectionStrings:DbConnection"]);}

MICRO ORMS : SIMPLE.DATA

REPO:public async Task<List<Book>> GetAll(){

return await _db.Book.All().ToList<Book>();//return await _db["Book"].All().ToList<Book>();

}

public async Task<Book> GetByID(int id){

return await _db.Book.Find(_db.Book.Id == id);//return await _db.Book.Get(id).Cast<Book>();

}

MICRO ORMS : SIMPLE.DATA

public async Task Add(Book book){

await _db.Book.Insert(book);}

public async Task Update(Book book){

await _db.Book.UpdateById(Id: book.Id, Name: book.Name);}

public async Task Delete(int id){

await _db.Book.DeleteById(id);}

MICRO ORMS : SERVICESTACK.ORMLITE

POCO

DYNAMIC OBJECTS

MULTIPLE RESULTS

STORED PROCEDURE

TRANSACTION

ASYNC

PROVIDERS: SqlServer, PostgreSQL, MySql, Sqlite.Mono, Sqlite.Windows, Oracle, Firebird, VistaDb, AWS RDS (PostgreSQL, Aurora, MySQL, MariaDB, SQL Server)

MICRO ORMS : SERVICESTACK.ORMLITE

CONFIG:public void ConfigureServices(IServiceCollection services){

services.AddScoped<ICookBookRepository, CookBookRepository>();}

CTOR:private readonly IDbConnectionFactory _dbFactory;

public CookBookRepository(){

_dbFactory = new OrmLiteConnectionFactory(Startup.Configuration["connectionStrings:DbConnection"], SqlServer2012Dialect.Provider);

}

MICRO ORM : SERVICESTACK.ORMLITE

REPO:public IEnumerable<Book> GetAll(){

using (IDbConnection dbConnection = _dbFactory.OpenDbConnection())

{return dbConnection.Select<Book>();//return await dbConnection.SelectAsync<Book>();

}}

public Book GetByID(int id){

using (IDbConnection dbConnection = _dbFactory.OpenDbConnection()) {

return dbConnection.Select<Book>(s => s.Id == id).FirstOrDefault();//return await dbConnection.SelectAsync<Book>(s => s.Id == id).FirstOrDefault();

}}

MICRO ORMS : SERVICESTACK.ORMLITE

public void Add(Book book){

using (IDbConnection dbConnection = _dbFactory.OpenDbConnection()) {

dbConnection.Insert<Book>(book);// await dbConnection.InsertAsync<Book>(book);

}}

public void Delete(int id){

using (IDbConnection dbConnection = _dbFactory.OpenDbConnection()) {

dbConnection.Delete<Book>(s => s.Id == id);// await dbConnection.DeleteAsync<Book>(s => s.Id == id);

}}

MICRO ORMS : SERVICESTACK.ORMLITE

public void Update(Book book){

using (IDbConnection dbConnection = _dbFactory.OpenDbConnection()) {

// dbConnection.Update<Book>(// dbConnection.UpdateAdd<Book>(// dbConnection.UpdateAll<Book>(// await dbConnection.UpdateOnlyAsync<Book>(

dbConnection.UpdateOnly<Book>(book,onlyFields: f => f.Name == book.Name,where: s => s.Id == book.Id

);}

}

LINKS

PETAPOCO

http://www.toptensoftware.com/petapoco/

https://github.com/CollaboratingPlatypus/PetaPoco

MASSIVE OK

https://github.com/FransBouma/Massive

ORMLITE OK

https://github.com/ServiceStack/ServiceStack.OrmLite

http://gistlyn.com/?collection=991db51e44674ad01d3d318b24cf0934&gist=a62b1e7a8da57c7d1fda95b3da5303eb

SIMPLEDATA OK

https://github.com/markrendle/Simple.Data

DAPPER OK

https://github.com/StackExchange/dapper-dot-net