Dubbi su EF code-first

martedì 18 novembre 2014 - 11.08
Tag Elenco Tags  C#

Gemini Profilo | Expert

Ciao a tutti
sto studiando EF code-first è ho alcuni dubbi:
1- Non mi è molto chiara la migration. Alcune operazioni vengono fatte da console vs, ma se devo caricare sul server, come faccio a riportare queste modifiche? O ho capito male io?
Quello che voglio capire è come aggiungere nuovi campi successivamente al db senza perdere i dati presenti.

2- Ho creato uno schema del db e ho previsto questa tabella: id | fkUser | fkAgenzia

Dove fkUser e fkAgenzia sono chiavi esterne delle tabelle Users e Agenzie. Ho visto che mappando le tabelle Agenzie e Users è possibile creare automaticamente questa tabella. Devo far creare automaticamente la tabella o posso crearla io?

3- il campo Guid viene convertito in 'uniqueidentifier'? Come faccio a inserire un campo 'money'?

Ma c'è un libro o un video tutorial in italiano? Ho trovato solo inglese

Grazie mille

0v3rCl0ck Profilo | Guru

>Ciao a tutti

Ciao

>sto studiando EF code-first è ho alcuni dubbi:

e fai benissimo

>1- Non mi è molto chiara la migration. Alcune operazioni vengono
>fatte da console vs, ma se devo caricare sul server, come faccio
>a riportare queste modifiche? O ho capito male io?

no, hai capito benissimo, le operazioni a server (in produzione), devono essere eseguite da console, in particolare con l'eseguibile Migrate.exe, questo perchè ti da pieno controllo di quello che stai facendo, specialmente quando si parla di produzione, dove non si vogliono fare cazzate

>Quello che voglio capire è come aggiungere nuovi campi successivamente
>al db senza perdere i dati presenti.

Le migrations code first sono quello che cerchi

Ti allego quello che ho appena inserito nelle demo del corso sqlsatparma:

"
---------------------------------------------------------------------------------------------------------------------

Per migrare in produzione un database CodeFirst si utilizza l'eseguibile Migrate.exe

Migrate.exe lo trovate nella cartella dove viene scaricato il pacchetto "Entity Framewok"
di solito nella cartella della solutions sotto: SolutionFolder\packages\EntityFramework.6.1.1\tools

Per migrare il database all'ultima versione basta specificare l'assembly e il file di configurazione:

Migrate.exe MDEF01.Demo.Migrations.exe /startupConfigurationFile="MDEF01.Demo.Migrations.exe.config"

Per migrare ad una specifica versione di migrazione:

Migrate.exe MDEF01.Demo.Migrations.exe /startupConfigurationFile="MDEF01.Demo.Migrations.exe.config" /targetMigration="InitialCreate"

Se la vostra migrazione è sviluppato leggendo file o dipendenze relative alla Working Directory:

Migrate.exe MDEF01.Demo.Migrations.exe /startupConfigurationFile="MDEF01.Demo.Migrations.exe.config" /startupDirectory="C:\MDEF01\MDEF01.Demo.Migrations\bin\Debug"

Specificare direttamente una connection string:

Migrate.exe MDEF01.Demo.Migrations.exe /connectionString="Server=(localdb)\mssqllocaldb;Database=MDEF01.Demo.Migrations;Trusted_Connection=True" /connectionProviderName="System.Data.SqlClient"

Per maggiori informazioni:
http://msdn.microsoft.com/data/jj618307

---------------------------------------------------------------------------------------------------------------------

E' anche possibile generare uno script (idempotente, da EF6) di creazione del database utilizzando il "Package Manager Console":

Per generare uno script completo da database vuoto:

Update-Database -Script -SourceMigration:$InitialDatabase

Gli script idempotenti possono aggiornare un database da qualsiasi versione esso siano fino all'ultima versione.

Per maggiori informazioni:
http://msdn.microsoft.com/en-us/data/jj591621

---------------------------------------------------------------------------------------------------------------------
"

>
>2- Ho creato uno schema del db e ho previsto questa tabella:
>id | fkUser | fkAgenzia
>
>Dove fkUser e fkAgenzia sono chiavi esterne delle tabelle Users
>e Agenzie. Ho visto che mappando le tabelle Agenzie e Users è
>possibile creare automaticamente questa tabella. Devo far creare
>automaticamente la tabella o posso crearla io?

se fai creare a EF il database, devi lasciarla creare a lui, di fatto è un aspetto puramente implementativo dei database relazionali (usare una tabella di collegamento per relazioni M-M), però puoi personalizzare il tutto...

se specifichi solo le proprietà di navigazione e la relazione:

protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<Product>() .HasMany(t => t.Orders) .WithMany(t => t.Products); }

allora si la tabella viene generata automaticamente con un determinato nome.

altrimenti puoi specificare un nome diverso per la tabella, e un nome diverso per le colonne chiave:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

>
>3- il campo Guid viene convertito in 'uniqueidentifier'? Come
>faccio a inserire un campo 'money'?

Per specificare che una proprietà decimal dovrà essere un money a db, puoi utilizzare le DataAnnotation, e cioè specificare un attributo sulla proprietà incriminata:

[Column(TypeName = "money")]

Altrimenti in maniera un po' più elegante e sopratutto disaccopiatta, facendo l'override dell'OnModelCreating e specificando il type da li:

public class MyDbContext : DbContext { public DbSet<Product> Products { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<Product>() .Property(t => t.Price) .HasColumnType("money"); } } public class Product { public int ProductId { get; set; } public string Name { get; set; } public decimal Price { get; set; } }

Oppure ancora più disaccopiato e modulare, per evitare di "sporcare" troppo il dbcontext:

public class MyDbContext : DbContext { public DbSet<Product> Products { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new ProductConfiguration()); } } public class ProductConfiguration : EntityTypeConfiguration<Product> { public ProductConfiguration() { this.Property(t => t.Price) .HasColumnType("money"); } } public class Product { public int ProductId { get; set; } public string Name { get; set; } public decimal Price { get; set; } }

>
>Ma c'è un libro o un video tutorial in italiano? Ho trovato solo
>inglese
>

Puoi provare dal portale entity framework dove in parte è stato anche tradotto in italiano: http://msdn.microsoft.com/it-it/data/ee712907.aspx

>Grazie mille
Prego!
Michael Denny | Microsoft Visual C# MVP
http://blogs.dotnethell.it/Regulator/
http://dennymichael.net
http://mvp.microsoft.com/mvp/Michael%20Denny-5000735
Twitter: @dennymic

0v3rCl0ck Profilo | Guru

Se invece vuoi avere il massimo controllo della tabella di collegamento, puoi anche fare così, spezzando la relazioni fisica tra classi molti a molti, e impostando le doppie relazioni 1 a molti classiche stile db, per ottenere poi di fatto la tua molti a molti, però con campi aggiuntivi:

using System; using System.Collections.Generic; using System.Data.Entity; namespace MDEF01.Extra.CompositeKey { internal class Program { private static void Main(string[] args) { using (var db = new MyDbContext()) { db.Database.Initialize(false); } Console.WriteLine("Premi invio per terminare l'applicazione..."); Console.ReadLine(); } } public class MyDbContext : DbContext { static MyDbContext() { Database.SetInitializer(new DropCreateDatabaseAlways<MyDbContext>()); } public DbSet<OrderDetail> OrderDetails { get; set; } public DbSet<Product> Products { get; set; } public DbSet<Order> Orders { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<OrderDetail>() .HasKey(t => new { t.OrderId, t.ProductId }); } } public class OrderDetail { public int OrderId { get; set; } public int ProductId { get; set; } public decimal UnitPrice { get; set; } public int Quantity { get; set; } public virtual Product Product { get; set; } public virtual Order Order { get; set; } } public class Product { public int ProductId { get; set; } public string Name { get; set; } // navigation properties public virtual ICollection<OrderDetail> OrderDetails { get; set; } public Product() { this.OrderDetails = new List<OrderDetail>(); } } public class Order { public int OrderId { get; set; } public DateTime OrderDate { get; set; } public DateTime ShippedDate { get; set; } // navigation properties public virtual ICollection<OrderDetail> OrderDetails { get; set; } public Order() { this.OrderDetails = new List<OrderDetail>(); } } }

ovviamente poi dato un ordine non è più così immediato avere tutti i prodotti "order.Products", ma dovrai passare dalla OrderDetail "order.Select(t => t.Product)", comunque sempre molto semplice


Michael Denny | Microsoft Visual C# MVP
http://blogs.dotnethell.it/Regulator/
http://dennymichael.net
http://mvp.microsoft.com/mvp/Michael%20Denny-5000735
Twitter: @dennymic

Gemini Profilo | Expert

Non so come ringraziarti

0v3rCl0ck Profilo | Guru

sono contento di averti aiutato


Michael Denny | Microsoft Visual C# MVP
http://blogs.dotnethell.it/Regulator/
http://dennymichael.net
http://mvp.microsoft.com/mvp/Michael%20Denny-5000735
Twitter: @dennymic
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2025
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5