Entity Framework 6 cambiare stringa di connessione a runtime

lunedì 03 novembre 2014 - 15.00
Tag Elenco Tags  VB.NET  |  .NET 4.0

totti240282 Profilo | Guru

Ciao,
tramite EF6 mi collego a un db .sdf , vorrei cambiare a runtime la stringa di connessione per puntare a diversi db che hanno la stessa struttura.

Come posso fare ?

Grazie.
C'è solo un capitano !!!!!!

0v3rCl0ck Profilo | Guru

ciao andrea,

con ef6 è piuttosto semplice, il DbContext prende come parametro di costruttore un "string nameOrConnectionString", a cui è possibile passare 3 tipologie, di stringa:

- il nome del database es.: "MyDatabase"
- il nome della connection string (presa da app.config) es.: "name=MyDatabase"
- la connection string per esteso es.: "Data Source=|DataDirectory|mydb1.sdf;"

quando si passa semplicemente il nome del database, quest'ultimo prima cerca se esiste una connection string nell'app.config con lo stesso nome, se non esiste, utilizza il nome per creare automaticamente il file .sdf, mentre per forzare il fatto che la connection string esista nell'app.config devi usare la sintassi "name=miodb".

qui è spiegato in dettaglio: http://msdn.microsoft.com/en-us/data/jj592674

si fa prima a provarlo:

using System.Data.Entity; namespace ConsoleApplication10 { class Program { static void Main(string[] args) { using (var db = new MyDbContext("mydb1")) { db.Database.Initialize(false); } } } public class Customer { public int CustomerId { get; set; } public string FirstName { get; set; } public string LastName { get; set; } } public class MyDbContext : DbContext { public MyDbContext(string nameOrConnectionString) : base(nameOrConnectionString) { Database.SetInitializer(new DropCreateDatabaseAlways<MyDbContext>()); } public DbSet<Customer> Customers { get; set; } } }

la prima volta che lo lanci vedrai che nella bin ti verrà creato un file mydb1.sdf

se cambi in

MyDbContext("mydb2")

e rilanci, vedrai che ti crea un db nuovo mydb2.sdf

altrimenti puoi inserire le connection string per esteso nell'app.config:

<connectionStrings> <add name="mydb1" connectionString="Data Source=|DataDirectory|mydb1.sdf;" providerName="System.Data.SqlServerCe.4.0" /> <add name="mydb2" connectionString="Data Source=|DataDirectory|mydb2.sdf;" providerName="System.Data.SqlServerCe.4.0" /> <add name="mydb3" connectionString="Data Source=|DataDirectory|mydb3.sdf;" providerName="System.Data.SqlServerCe.4.0" /> </connectionStrings>

e utilizzarlo implicitamente:

MyDbContext("mydb3")

oppure esplicitamente:

MyDbContext("name=mydb3")

spero di avere risposto alla tua domanda, sostanzialmente se vuoi cambiare la connessione del db "al volo", non devi fare altro che istanziare il dbcontext con il db opportuno.



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

totti240282 Profilo | Guru

Questa è una buona soluzione però mi costringe a tenere n stringhe di connessione nel config.

La soluzione che ho adottato è tenere una stringa di connessione al db, poi una volta instanziato il context gli cambio la stringa di connessione e anche la password.


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

0v3rCl0ck Profilo | Guru

Non sei obbligato a tenerle nel config, non hai visto che ti ho postato 3 metodi differenti di passare la connection string?

- il nome del database es.: "MyDatabase"
- il nome della connection string (presa da app.config) es.: "name=MyDatabase"
- la connection string per esteso es.: "Data Source=|DataDirectory|mydb1.sdf;"

"la connection string per esteso": quando crei il DbContext, puoi passare come parametro anche la connection string completa, quindi puoi impostare la conn string così:

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

non cambierei la connection string dopo avere chiamato il costruttore, teoricamente con la connection string non dovrebbe farci niente fino alla prima chiamata alle entità, ma non ne sono sicuro (tipo il controllo della versione del db versus il edml quando viene fatto?) e comunque potrebbe cambiare nel tempo, quindi meglio passare la giusta connection string subito nel costruttore sfruttando il configurationmanager come ti ho fatto vedere sopra.

Poi eventualmente creati una classe ConnectionStringHelper dove metti quella logica, giusto per darti la possibilità di cambiarla nel tempo, e di non schiantare le replace in ogni punto.

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




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

totti240282 Profilo | Guru

è proprio qui il problema quando creo il context non ci sono parametri per passargli la stringa di connessione.
C'è solo un capitano !!!!!!

0v3rCl0ck Profilo | Guru

devi aggiungere il costruttore nel tuo DbContext, si vede nel codice che ti avevo mandato prima:

public class MyDbContext : DbContext { public MyDbContext(string nameOrConnectionString) : base(nameOrConnectionString) { Database.SetInitializer(new DropCreateDatabaseAlways<MyDbContext>()); } public DbSet<Customer> Customers { get; set; } }

forse non l'hai visto perchè non te l'avevo postato in vb.net:

Public Class MyDbContext Inherits DbContext Public Sub New(nameOrConnectionString As String) MyBase.New(nameOrConnectionString) Database.SetInitializer(New DropCreateDatabaseAlways(Of MyDbContext)()) End Sub Public Property Customers() As DbSet(Of Customer) Get Return m_Customers End Get Set m_Customers = Value End Set End Property Private m_Customers As DbSet(Of Customer) End Class

in sostanza devi aggiungere il costruttore, togliendo l'initializer che a te non serve:

Public Sub New(nameOrConnectionString As String) MyBase.New(nameOrConnectionString) End Sub


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

totti240282 Profilo | Guru

Grazie ho approfondito il discorso su internet e consigliano di fare l'override altrimenti ad ogni compilazione viene cancellata la modifica.
C'è solo un capitano !!!!!!

0v3rCl0ck Profilo | Guru

non ho capito questa tua ultima affermazione, quindi hai utilizzato il costruttore ?


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

totti240282 Profilo | Guru

Si ma ho fatto l'override del costruttore, cosi ad ogni compilazione o cambiamento di struttura non si perde la modifica.
C'è solo un capitano !!!!!!
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