Sto provando a creare un nuovo database utilizzando il primo concetto di codice di Entity Framework. Tuttavia, quando si esegue il codice, il database non viene creato (utilizzando l'impostazione DropCreateDatabaseIfModelChanges
), sebbene il codice funzioni correttamente. Vedo la seguente eccezione quando cerco di ottenere qualcosa dal database.Entity Framework 5 code-first non crea il database
Il mio progetto è di installazione utilizzando un DataAccess
livello separato con un servizio generico e la costruzione repository. Quindi tutte le mie entità, repository e anche il contesto del database sono in un progetto separato all'interno della soluzione.
Il file global.asax
contiene il seguente codice.
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<MyContext>());
Questo dovrebbe inizializzare un nuovo database se non è lì, giusto?
La classe di contesto del database è simile alla seguente;
namespace Website.DAL.Model
{
public class MyContext : DbContext
{
public IDbSet<Project> Projects { get; set; }
public IDbSet<Portfolio> Portfolios { get; set; }
/// <summary>
/// The constructor, we provide the connectionstring to be used to it's base class.
/// </summary>
public MyContext()
: base("MyConnectionString")
{
}
static MyContext()
{
try
{
Database.SetInitializer<MyContext>(new DropCreateDatabaseIfModelChanges<MyContext>());
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// This method prevents the plurarization of table names
/// </summary>
/// <param name="modelBuilder"></param>
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention>();
}
}
}
Ho creato questa classe seguendo diversi tutorial e articoli su Internet. È tutto nuovo per me, ma per quanto posso vedere tutto sembra corretto finora. Quindi ora le due entità che sto usando. Si chiamano "Progetto" e "Portafoglio". Sembrano così;
public class Portfolio
{
[Key]
public Guid Id { get; set; }
public String Name { get; set; }
public DateTime StartDate { get; set; }
public DateTime? EndDate { get; set; }
public bool IsPublished { get; set; }
public virtual ICollection<Project> Projects { get; set; }
}
E
public class Project
{
[Key]
public Guid Id { get; set; }
public DateTime StartDate { get; set; }
public DateTime? EndDate { get; set; }
public bool IsPublished { get; set; }
public String Title { get; set; }
}
Il database che sto utilizzando è in esecuzione su un server esterno, è venuto con il fornitore di hosting che sto utilizzando. Ho un database SQL Server attivo e funzionante e la stringa di connessione al database si trova nello web.config
del progetto del sito web. Ho già provato a rimuovere il database e lasciare che il codice lo ricrei, che purtroppo non ha funzionato. Mi sto perdendo qualcosa di ovvio qui? O potrebbe essere una cosa semplice come diritti di accesso al server per creare database?
Nota: quando eseguo il comando Database-Update -Script
per generare il codice SQL, sembra che vengano create le istruzioni SQL corrette per creare tutte le tabelle.
UPDATE 1: OK, grazie ad alcuni commenti sono arrivato un po 'oltre. Ho aggiunto due proprietà alle mie entità per forzare alcune modifiche e ho anche creato un inizializzatore personalizzato come questo;
public class ForceDeleteInitializer : IDatabaseInitializer<MyContext>
{
private readonly IDatabaseInitializer<MyContext> _initializer = new DropCreateDatabaseIfModelChanges<MyContext>();
public ForceDeleteInitializer()
{
//_initializer = new ForceDeleteInitializer();
}
public void InitializeDatabase(MyContext context)
{
//This command is added to prevent open connections. See http://stackoverflow.com/questions/5288996/database-in-use-error-with-entity-framework-4-code-first
context.Database.ExecuteSqlCommand("ALTER DATABASE borloOntwikkel SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
_initializer.InitializeDatabase(context);
}
}
Ho anche rimosso l'inizializzazione dal costruttore del mio contesto, quindi questo significa che ho rimuovere questa riga di codice;
Database.SetInitializer<MyContext>(new DropCreateDatabaseIfModelChanges<MyContext>());
Dopo che ho aggiunto queste tre linee al mio Global.file asax;
Database.SetInitializer(new ForceDeleteInitializer());
MyContext c = new MyContext();
c.Database.Initialize(true);
In fase di debug ora sto ricevendo questa eccezione;
questo mi dà le seguenti informazioni:
- InnerException dice: Il provider non ha restituito un ProviderManifestToken
- InnerException nel InnerException dice: "Per questa operazione una connessione alla masterdatabase è richiesto.Una connessione non può essere larghezza fatta il 'master'-database perché la connessione originale è aperto e i riferimenti sono stati rimossi dalla connessione Si prega di fornire una connessione non aperta"
Dopo queste azioni il database è inaccessibile, quindi molto probabilmente cancellato ..
Cosa può eventualmente essere fatto su questo? È molto probabile che non riesca ad accedere al database master perché il mio hostingprovider non mi darà il diritto di accesso corretto per il corso.
Il codice e la configurazione sembrano OK, probabilmente sei bloccato sulla situazione di hosting. EF vuole creare il tuo Db con una speciale tabella di supporto (1 o 2 hash). Forse puoi copiarlo da un Db locale e spostarlo nel Db ospitato? –
L'account utente che esegue il codice ha le autorizzazioni necessarie per eliminare e creare database? – jlew
@Henk, ho appena provato a eseguire lo script SQL generato. Ha creato per me un tavolo __MigrationHistory con un record. Ho anche modificato il costruttore del mio contesto aggiungendo la riga 'this.Database.Initialize (true)'. Questo non mi ha dato un errore, ma non ho creato alcun tavolo. Ho quindi eliminato il record dalla tabella MigrationHistory e ho avuto di nuovo lo stesso errore. Quindi cercherò di eseguirlo su un database locale ora e vedere cosa succede. – Rob