entity framework 6 for developers, code-first!

40
#sqlsatParma #sqlsat355 November 22 nd , 2014 Entity Framework 6 for developers Code-First Michael Denny @dennymic about.me/micdenny

Upload: michael-denny

Post on 15-Jul-2015

430 views

Category:

Software


4 download

TRANSCRIPT

#sqlsatParma

#sqlsat355November 22nd, 2014

Entity Framework 6 for developers

Code-First

Michael Denny

@dennymic

about.me/micdenny

#sqlsatParma

#sqlsat355November 22nd, 2014

Sponsors

#sqlsatParma

#sqlsat355November 22nd, 2014

Organizers

#sqlsatParma

#sqlsat355November 22nd, 2014

Speaker info

Microsoft Visual C# MVP

Blogs: [ITA] http://blogs.dotnethell.it/regulator/

[ENG] http://dennymichael.net/

Community/Forum: http://www.dotnethell.it

Twitter: @dennymic

More details on: http://about.me/micdenny/

#sqlsatParma

#sqlsat355November 22nd, 2014

Agenda

Concetti ORM

Scegliere tra designer o codice

Entity Framework Code-First in azione

Evolvere il database: Code-First Migrations

Importare un database esistente

Strumenti di Logging e Profiling

What’s Next

Q&A

#sqlsatParma

#sqlsat355November 22nd, 2014

Visual Studio Community 2013

Include tutte le funzionalità di Visual Studio Professional 2013

Sviluppatori indipendenti per applicazioni sia free che a pagamento, studenti,

collaboratori open source, e organizzazioni con team fino a 5 persone

#sqlsatParma

#sqlsat355November 22nd, 2014

Concetti ORM

Integrazione tra OOP e RDBMS

Persistenza dei dati con interfaccia

unificata

Interfaccia orientata agli oggetti

Astrazione sul tipo di database utilizzato

Sviluppo nel vostro linguaggio (C# )

Riduzione di codice ripetitivo CRUD

Codice più «pulito» e ben strutturato

#sqlsatParma

#sqlsat355November 22nd, 2014

Entity Framework

Implementazione ORM open-source per

ADO.NET

Librerie su NuGet

Lazy-Load

Caching (object, query plan, metadata)

Gestione della Concorrenza

Repository Pattern (DbSet)

Unit of Work (DbContext)

http://msdn.microsoft.com/data/ee712907

#sqlsatParma

#sqlsat355November 22nd, 2014

Architettura EF

#sqlsatParma

#sqlsat355November 22nd, 2014

Database

Esistente

Database First• Creazione modello partendo da un

DB esistente (Reverse Engineering)

• Classi auto-generate dal modello

Code First (Database Esistente)• Definizione classi da codice

• Strumenti per l’auto-generazione delle

classi partendo da un DB esistente

(Reverse Engineering)

Nuovo

Database

Model First• Creazione modello da designer

• Database creato dal modello

• Classi auto-generate dal modello

Code First (Nuovo Database)• Definizione classi da codice

• Database creato dal modello

• Possibilità di evolvere il database

utilizzando le Migrations

Designer o Codice

#sqlsatParma

#sqlsat355November 22nd, 2014

EF Code-First in azione

Modellazione dati

Convenzioni

Operazioni basilari (CRUD)

Query LINQ

Personalizzazioni con Data Annotation

Personalizzazioni con Fluent API

#sqlsatParma

#sqlsat355November 22nd, 2014

Modellazione dati

POCO class

public class Blog{

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

public virtual ICollection<Post> Posts { get; set; } }

public class Post{

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

public int BlogId { get; set; }

public virtual Blog Blog { get; set; } }

#sqlsatParma

#sqlsat355November 22nd, 2014

Modellazione dati

Le proprietà di navigazione definiscono il tipo di relazione

tra le entità in base al tipo di ritorno:

Riferimento, per relazioni uno a uno

Collezione, per relazioni uno a molti

Includere sempre anche la foreign

key sulla classe che rappresenta

l’oggetto dipendente

Virtual abilita il Lazy Loading

vedi: http://msdn.microsoft.com/data/jj574232

public class Blog{

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

public virtual ICollection<Post> Posts{ get; set; }

}

public class Post{

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

public int BlogId { get; set; }

public virtual Blog Blog { get; set; } }

#sqlsatParma

#sqlsat355November 22nd, 2014

DbContext e DbSet

Responsabile dell’interazione con il database

In grado di creare il database dal modello classi

Gestisce e popola gli oggetti entità

Rileva le modifiche (change tracking)

Persiste le informazioni a database

Implementa la Unit of Work (SaveChanges)

Espone proprietà DbSet (Repository Pattern) che

rappresentano collezioni di specifiche entità

public class BloggingContext : DbContext{

public DbSet<Blog> Blogs { get; set; }public DbSet<Post> Posts { get; set; }

}

#sqlsatParma

#sqlsat355November 22nd, 2014

DEMO 01

Modellazione con POCO class

DbContext

DbSet

Creazione database

#sqlsatParma

#sqlsat355November 22nd, 2014

Convenzioni

System.Data.Entity.ModelConfiguration.Conventions

Chiave primaria

Relazioni

Connection string

Rimuovere una convenzione

Convenzioni personalizzate

#sqlsatParma

#sqlsat355November 22nd, 2014

Convenzioni: Chiave Primaria

Nome proprietà "Id" (non case sentitive)

Nome classe seguito da "Id", es.: "UserId"

Identity Column se il tipo è numerico o GUID

public class Blog{

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

public virtual ICollection<Post> Posts { get; set; } }

#sqlsatParma

#sqlsat355November 22nd, 2014

Basate sulle proprietà di navigazione

Foreign key deve avere lo stesso tipo dato della chiave

primaria e nome: 1. «nome proprietà di navigazione»«nome proprietà chiave primaria» es.:

BlogBlogId

2. «nome classe principale»«nome proprietà chiave primaria» es.:

BlogBlogId

3. «nome proprietà chiave primaria»

es.: BlogId

Non è case sensitive

FK nullable = relazione opzionale

Cascade delete se FK != nullable

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; } }

public class Blog{

public int BlogId { get; set; }}

Convenzioni: Relazioni

#sqlsatParma

#sqlsat355November 22nd, 2014

Convenzioni: Connection String

DbContext() = Code-First + IConnectionFactory:

Nome db: «namespace».«nome classe dbcontext>

Server: SQL Express oppure LocalDb, se entrambi sono

installati, viene utilizzato SQL Express

DbContext("MyDatabase") = Code-First +

IConnectionFactory:

Nome db: MyDatabase

Server: SQL Express o LocalDb

Se nell’app.config esiste una connection string con lo stesso

nome, allora viene usata quella e bypassato il factory

DbContext("name=MyDatabase") = Code-First:

Forza la dichiarazione della connection string su app.config

#sqlsatParma

#sqlsat355November 22nd, 2014

Convenzioni: Personalizzazioni

Rimuovere una convenzione

Convenzioni personalizzate

public class BloggingContext : DbContext{

protected override void OnModelCreating(DbModelBuilder modelBuilder){

modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();}

}

public class BloggingContext : DbContext{

protected override void OnModelCreating(DbModelBuilder modelBuilder){

modelBuilder.Properties<int>().Where(t => t.Name.StartsWith("id", StringComparison.InvariantCultureIgnoreCase)).Configure(t => t.IsKey().HasColumnOrder(1));

} }

#sqlsatParma

#sqlsat355November 22nd, 2014

Convenzioni

IdKeyDiscoveryConvention

Rileva le proprietà per la chiave primaria

PluralizingTableNameConvention

Nome tabella = plurale nome classe

PluralizingEntitySetNameConvention

Proprietà di navigazione = plurale nome tipo dato

DecimalPropertyConvention

Setta la precision e la scale (18,2) per le proprietà decimali

Tanti tanti altri...

Vedi: System.Data.Entity.ModelConfiguration.Conventions

#sqlsatParma

#sqlsat355November 22nd, 2014

Operazioni basilari (CRUD)

using (var db = new BloggingContext()) {

var blog = new Blog();blog.Name = "Il mio primo blog";db.Blogs.Add(blog);db.SaveChanges();

}

using (var db = new BloggingContext()) {

var blog = db.Blogs.Find(1);Console.WriteLine(blog.Name);

}

using (var db = new BloggingContext()) {

var blog = db.Blogs.Find(1);blog.Name = "Nome modificato!!";db.SaveChanges();

}

using (var db = new BloggingContext()) {

var blog = db.Blogs.Find(1);db.Blogs.Remove(blog);db.SaveChanges();

}

#sqlsatParma

#sqlsat355November 22nd, 2014

DEMO 02

Create

Read

Update

Delete

#sqlsatParma

#sqlsat355November 22nd, 2014

LINQ Query

Lambda Expression

Query LINQ: Filtrare

using (var db = new BloggingContext()) {

var results = from post in db.Postswhere post.Title.Contains("trovami")select post;

foreach (var result in results)Console.WriteLine(result.Title);

}

using (var db = new BloggingContext()) {

var results = db.Posts.Where(post => post.Title.Contains("trovami"));

foreach (var result in results)Console.WriteLine(result.Title);

}

SELECT

[Extent1].[PostId] AS [PostId],

[Extent1].[Title] AS [Title],

[Extent1].[Content] AS [Content],

[Extent1].[BlogId] AS [BlogId]

FROM

[dbo].[Posts] AS [Extent1]

WHERE

[Extent1].[Title] LIKE N'%trovami%'

#sqlsatParma

#sqlsat355November 22nd, 2014

Query LINQ: Ordinare

using (var db = new BloggingContext()) {

var results = from post in db.Postsorderby post.Titleselect post;

foreach (var result in results)Console.WriteLine(result.Title);

}

using (var db = new BloggingContext()) {

var results = db.Posts.OrderBy(t => t.Title);

foreach (var result in results)Console.WriteLine(result.Title);

}

using (var db = new BloggingContext()) {

var results = db.Posts.Where(t => t.Content.Contains("trovami")).OrderBy(t => t.Title);

foreach (var result in results)Console.WriteLine(result.Title);

}

SELECT

[Extent1].[PostId] AS [PostId],

[Extent1].[Title] AS [Title],

[Extent1].[Content] AS [Content],

[Extent1].[BlogId] AS [BlogId]

FROM

[dbo].[Posts] AS [Extent1]

ORDER BY

[Extent1].[Title] ASC

SELECT

[Extent1].[PostId] AS [PostId],

[Extent1].[Title] AS [Title],

[Extent1].[Content] AS [Content],

[Extent1].[BlogId] AS [BlogId]

FROM

[dbo].[Posts] AS [Extent1]

WHERE

[Extent1].[Content] LIKE N'%trovami%'

ORDER BY

[Extent1].[Title] ASC

LINQ Query OrderBy

Lambda Expression OrderBy

Lambda Expression Where + OrderBy

#sqlsatParma

#sqlsat355November 22nd, 2014

Query LINQ: Join(are)

Esplicite

Implicite

using (var db = new BloggingContext()) {

var results = from blog in db.Blogsjoin post in db.Posts on blog.BlogId equals post.BlogIdselect new{

BlogName = blog.Name,PostTitle = post.Title

};foreach (var result in results)

Console.WriteLine("blog: {0} post: {1}", result.BlogName, result.PostTitle); }

using (var db = new BloggingContext()) {

var results = from blog in db.Blogsfrom post in blog.Postsselect new{

BlogName = blog.Name, PostTitle = post.Title

};foreach (var result in results)

Console.WriteLine("blog: {0} post: {1}", result.BlogName, result.PostTitle); }

SELECT

[Extent1].[BlogId] AS [BlogId],

[Extent1].[Name] AS [Name],

[Extent2].[Title] AS [Title]

FROM

[dbo].[Blogs] AS [Extent1]

INNER JOIN

[dbo].[Posts] AS [Extent2]

ON [Extent1].[BlogId] = [Extent2].[BlogId]

#sqlsatParma

#sqlsat355November 22nd, 2014

Query: Stored Procedure

Raw SQL Queries

http://msdn.microsoft.com/data/jj592907public class BloggingContext : DbContext{

public DbSet<Blog> Blogs { get; set; }public DbSet<Post> Posts { get; set; }

public Blog GetBlogById(int blogId){

return this.Blogs.SqlQuery("proc_GetBlogById @p0", blogId).FirstOrDefault();

}

public Blog GetBlogById2(int blogId){

return this.Blogs.SqlQuery("proc_GetBlogById @BlogId",

new SqlParameter("@BlogId", blogId)).FirstOrDefault();

} }

#sqlsatParma

#sqlsat355November 22nd, 2014

Strumenti di Logging

Proprietà Log a delegato

Personalizzazione del contenuto e del formato

Sistema di intercettazione a moduli per

maggiore controllo e flessibilità

Gli Interceptor possono essere aggiunti da

config senza dovere ricompilare il progetto

BloggingContext.Database.Log = Console.Write;

#sqlsatParma

#sqlsat355November 22nd, 2014

DEMO 03

Filtrare

Ordinare

Join(are)

Stored Procedure

Logging

#sqlsatParma

#sqlsat355November 22nd, 2014

Evolvere il database: Code-First Migrations

Sempre sotto il nostro controllo

Personalizzazioni (anche estreme) da

codice

Semplicità di utilizzo

Enable-Migrations

Add-Migration

Update-Database

http://msdn.microsoft.com/data/jj591621

#sqlsatParma

#sqlsat355November 22nd, 2014

DEMO 04

Enable-Migrations

Add-Migrations

Update-Database

Migrate.exe

packages\EntityFramework.6.1.1\tools

#sqlsatParma

#sqlsat355November 22nd, 2014

Importare un database esistente

Da zero senza reverse engineering

Con strumenti di automazione:

Entity Framework Tools (incluso in VS2013)

www.microsoft.com/download/details.aspx?id=40762

Entity Framework Power Tools (NuGet)

EntityFramework Reverse POCO Generator (NuGet)

Code First Migrations anche per database

esistenti/importati

http://msdn.microsoft.com/data/dn579398

#sqlsatParma

#sqlsat355November 22nd, 2014

DEMO 05

Importare un database esistente

Entity Framework Tools

Entity Framework Power Tools

EntityFramework Reverse POCO Generator

#sqlsatParma

#sqlsat355November 22nd, 2014

Strumenti di Profiling

SQL Server Profiler (Microsoft)

SQL XEvent Profiler (free Idera)

EF Profiler (commerciale, installer

HibernatingRhinos.com)

ORM Profiler (commerciale, NuGet)

LINQ Insight Express (free, NuGet)

#sqlsatParma

#sqlsat355November 22nd, 2014

What’s Next

Versione 7 più leggera ed estensibile

Sarà disponibile per nuove piattaforme (Store

App, Phone App, Net Core, Mac, Linux)

Abiliterà nuovi data store, come sistemi non-

relazionali

Il passaggio a EF7 sarà semplificato il più

possibile (DbContext e DbSet saranno presenti)

Sviluppato e disponibile in pre-alpha su GitHub

https://github.com/aspnet/EntityFramework

#sqlsatParma

#sqlsat355November 22nd, 2014

In pillole…

Include(t => t.Posts) evita il lazy loading

http://msdn.microsoft.com/data/jj574232

Find(1) ricerca per chiave

http://msdn.microsoft.com/data/jj573936

Entity<>.ToTable("Posts", "Blog")

per creare Posts nello schema Blog

Async Query & Save

http://msdn.microsoft.com/data/jj819165

CRUD con Stored Procedure

http://msdn.microsoft.com/data/dn468673

#sqlsatParma

#sqlsat355November 22nd, 2014

In pillole…

Considerazioni sulle performance

http://msdn.microsoft.com/data/hh949853

Migliorare lo startup dell’applicazione con NGen

http://msdn.microsoft.com/data/dn582034

Pre-generare le Mapping Views (EDM) per

velocizzare dell’inizializzazione del DbContext

http://msdn.microsoft.com/data/dn469601

Gestione della concorrenza ottimistica

http://msdn.microsoft.com/data/jj592904

#sqlsatParma

#sqlsat355November 22nd, 2014

In pillole…

Migrate.exe per controllare e automatizzare il

processo di migrazione del database

http://msdn.microsoft.com/data/jj618307

AsNoTracking()

http://msdn.microsoft.com/data/jj556203

Disabilitare il tracking automatico

http://msdn.microsoft.com/data/jj556205

Unit Test: testare isolandosi dal database

http://msdn.microsoft.com/data/dn314429

#sqlsatParma

#sqlsat355November 22nd, 2014

Q&A

Questions?

#sqlsatParma

#sqlsat355November 22nd, 2014

THANKS!

#sqlsatParma

#sqlsat355