11

sto ottenendo questo errore quando provo ad usare il codice prime migrazioni.Ottenere 'Contesto non è costruibile. Aggiungere un costruttore di default o di fornire un'implementazione di IDbContextFactory ".

mio contesto ha un costruttore con il nome di connessione.

public class VeraContext : DbContext, IDbContext 
{ 
    public VeraContext(string NameOrConnectionStringName = "VeraDB") 
     : base(NameOrConnectionStringName) 
    { 
    } 

    public IDbSet<User> Users { get; set; } 
    public IDbSet<Product> Products { get; set; } 
    public IDbSet<IntCat> IntCats { get; set; } 
} 

Questo nome della connessione viene iniettato con Ninject quando il progetto viene eseguito, ho anche specificato come predefinito, come nel codice di cui sopra, ma questo non ha aiutato.

kernel.Bind<IDbContext>() 
    .To<VeraContext>() 
    .WithConstructorArgument("NameOrConnectionStringName", "VeraDB"); 

quando provo ad aggiungere migrazioni con "Attiva-mi grations" è getta l'errore:

The target context 'VeraData.EF.Infrastructure.VeraContext' is not constructible. Add a default constructor or provide an implementation of IDbContextFactory.

Se rimuovo il costruttore da VeraContext che funzionerà, ma crea un altro database con VeraData.EF.Infrastructure.VeraContext come il suo nome.

Suppongo che ninject passi solo la stringa di connessione quando il progetto è in esecuzione e non quando utilizzo le migrazioni prima del codice. Ad ogni modo posso inserire/fornire un valore predefinito per il nome della connessione quando si utilizzano le migrazioni prima del codice?

+1

Tutte le cose di tipo ninject si verificano quando qualcuno da qualche parte sta facendo un 'Kernel.Get'.Devi aggiungere un ctor predefinito o aspettare che qualcuno ti dica come collegare il materiale delle migrazioni per costruire oggetti tramite Ninject (che immagino sia ciò che stai facendo!). –

+0

Dovresti implementare 'IDbContextFactory' affinché i risultati siano coerenti (o la tua migrazione dal codice non funzionerà, ecc.). In sostanza, hai bisogno di un ctor predefinito (questo è l'errore), ma solo implementarlo porterebbe a problemi. – NSGaga

+0

L'IDbContextFactory non è adatto all'iniezione, semplicemente non funzionerà, in base alla progettazione. Non si vede ancora il punto ... – nicodemus13

risposta

16

In sostanza, è necessario un ctor predefinito (questo è l'errore), ma l'implementazione potrebbe portare a problemi.

Dovresti implementare lo IDbContextFactory affinché i risultati siano coerenti (oppure la migrazione dal codice non funzionerà, ecc.).

Migrations actually call your default constructor to make a connection. So you're other ctor won't matter much.

Ecco la base di fabbrica ...

public class MyContextFactory : IDbContextFactory<MyContext> 
{ 
    public MyContext Create() 
    { 
     return new MyDBContext("YourConnectionName"); 
    } 
} 

Si dovrebbe che si combinano con l'iniezione, iniettare e costruire la vostra DbContext come si desidera.

+0

Puoi spiegare cosa intendi più avanti, non puoi iniettare, dato che 'Create()' non assume parametri e ci deve essere un costruttore predefinito, che è sempre quello chiamato - quindi, da nessuna parte per iniettare. Almeno, nessuna iniezione del costruttore. – nicodemus13

+0

@ nicodemus13 era molto tempo fa, ma, come ricordo, è per garantire una costruzione coerente di DbContext. spesso EF invoca il ctor predefinito per automatismo, che lo si voglia o no, quindi è necessario averne uno e il ctor personalizzato non viene chiamato. Factory è principalmente per le chiamate EF, è possibile utilizzare normalmente l'iniezione su DbContext. Ma b) per quanto mi ricordi della maggior parte dei contenitori IoC (non uso molto il ninject) ho modo di definire per es. container.Create e poi qualche metodo anonimo per ingaggiare la fabbrica (se la fabbrica è più complessa, quindi è necessario analizzarla, altrimenti come ho detto) – NSGaga

+1

@NSGaga - Qualsiasi motivo per cui non è possibile iniettare DbContext o la stringa di connessione in MyContextFactory tramite il costruttore e quindi restituire DbContext anziché new'up su un nuovo DbContext nel metodo di creazione? –

1

per completare @ nccsbim071 risposta, devo aggiungere altro una cosa ... questa opzione non piace costruttore con i parametri di default ... per esempio:

public MyContext(bool paramABC = false) : base("name=Entities") {...} 

invece devi creare un costruttore non parametrico (predefinito) e il costruttore di parametri come in vecchio modo.

public MyContext() :base("name=Entities") {...} 
public MyContext(bool paramABC) : this() {...} 

NOTA:

  • Entities in questo caso significa il nome della stringa di connessione ... Per convenzione, il nome del contesto è lo stesso come il nome della stringa di connessione e poiché MyContext non è la stessa come Entities, è necessario specificarlo manualmente.
Problemi correlati