Sto provando ad usare la finestra interattiva c # per testare rapidamente parte del mio codice. Mi imbatto in problemi quando provo a testare il codice relativo a DbContext (EF6).
Capisco che ho bisogno di passare la stringa di connessione in quanto la finestra interattiva non caricherà il file App.config, quindi ho sovrascritto il costruttore che specifica la stringa di connessione.
Devo anche dire che sto usando il database Oracle con il provider ODP.NET.
Ecco il codice che sto cercando di eseguire sulla finestra interattiva:
#r "MyProjPath\bin\Debug\CsCore.EntityDomain.dll"
#r "MyProjPath\bin\Debug\EntityFramework.dll"
#r "MyProjPath\bin\Debug\EntityFramework.SqlServer.dll"
#r "MyProjPath\bin\Debug\Oracle.ManagedDataAccess.dll"
#r "MyProjPath\bin\Debug\Oracle.ManagedDataAccess.EntityFramework.dll"
var ctx = new CsCore.EntityDomain.Pivot.PivotContext("Data Source=MyDataSource;User Id=MyUser;Password=MyPassword;");
ctx.ReconciliationRules.FirstOrDefault()
e questa è l'eccezione che ottengo
The underlying provider failed on Open.
+ System.Data.Entity.Core.EntityClient.EntityConnection.Open()
+ System.Data.Entity.Core.Objects.ObjectContext.EnsureConnection(bool)
+ System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction<T>(Func<T>, System.Data.Entity.Infrastructure.IDbExecutionStrategy, bool, bool)
+ System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute<TResult>(Func<TResult>)
+ ObjectQuery<T>.GetResults(Nullable<System.Data.Entity.Core.Objects.MergeOption>)
+ LazyEnumerator<T>.MoveNext()
+ System.Linq.Enumerable.FirstOrDefault<TSource>(IEnumerable<TSource>)
+ System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.ExecuteSingle<TResult>(IEnumerable<TResult>, System.Linq.Expressions.Expression)
+ System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute<TResult>(System.Linq.Expressions.Expression)
+ System.Data.Entity.Internal.Linq.DbQueryProvider.Execute<TResult>(System.Linq.Expressions.Expression)
+ System.Linq.Queryable.FirstOrDefault<TSource>(IQueryable<TSource>)
Il mio DbContext si presenta così:
public class PivotContext : DbContext
{
public virtual DbSet<PivotReconciliationRule> ReconciliationRules { get; set; }
public PivotContext() : this("name=myConnectionStringName")
{
}
public PivotContext(string nameOrConnectionString) : base(nameOrConnectionString)
{
Database.SetInitializer<PivotContext>(null);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("MYSCHEMA");
base.OnModelCreating(modelBuilder);
}
}
Penso che la ragione sia che non sono in grado di specificare il fornitore corretto. Qualcuno è riuscito a utilizzare il codice EntityFramework code-first (su Oracle) che funziona dalla finestra interattiva c #?
Molte grazie in anticipo.
Nicola
Sono finalmente riuscito a farlo funzionare.
Prima di tutto ricevevo il messaggio "Il provider sottostante non è riuscito su Open." perché EF non è stato in grado di ottenere il fornitore e la fabbrica di connessione corretti. Stava infatti cercando di utilizzare la factory di connessione SqlServer anziché quella di Oracle. In un approccio basato sul database, è possibile che sia stato creato DbContext da EntityConnection, che specifica il provider. Purtroppo sembra che in questo caso sia necessario fornire anche il modello, che non è applicabile al codice prima.
Alla fine ho risolto il setup provider / fabbrica seguendo le informazioni in questo post . Il codice csx corrispondente è:
System.Data.Entity.DbConfiguration.Loaded += (_, a) =>
{
var services = Oracle.ManagedDataAccess.EntityFramework.EFOracleProviderServices.Instance;
a.ReplaceService<System.Data.Entity.Core.Common.DbProviderServices>((s, k) => services);
var factory = new Oracle.ManagedDataAccess.EntityFramework.OracleConnectionFactory();
a.ReplaceService<System.Data.Entity.Infrastructure.IDbConnectionFactory>((s, k) => factory);
};
Dopo averlo fatto ho ancora ricevuto il seguente errore: Impossibile determinare il nome del provider per la factory provider di tipo "Oracle.ManagedDataAccess.Client.OracleClientFactory". Assicurarsi che il provider ADO.NET sia installato o registrato nella configurazione dell'applicazione.
Ciò era dovuto al fatto che OracleClientFactory non era associato a un provider di entità framework (dalla sezione "entityFramework"). Non ero in grado di farlo direttamente dal codice. Ho finito per aggiungere la sezione "entityFramework" al mio machine.config:
Dichiarazione delle configurazioni:
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
<section name="oracle.manageddataaccess.client" type="OracleInternal.Common.ODPMSectionHandler, Oracle.ManagedDataAccess, Version=4.122.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
contenuto di configSection:
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="Oracle.ManagedDataAccess.Client" type="Oracle.ManagedDataAccess.EntityFramework.EFOracleProviderServices, Oracle.ManagedDataAccess.EntityFramework, Version=6.122.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
<system.data>
<DbProviderFactories>
<remove invariant="Oracle.ManagedDataAccess.Client" />
<add name="ODP.NET, Managed Driver" invariant="Oracle.ManagedDataAccess.Client" description="Oracle Data Provider for .NET, Managed Driver" type="Oracle.ManagedDataAccess.Client.OracleClientFactory, Oracle.ManagedDataAccess, Version=4.122.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
... other staff that was already there
</DbProviderFactories>
</system.data>
Con queste configurazioni, ho finalmente potuto usare il mio codice EF6 codice Oracle prima nella finestra interattiva c #.
Prima di tutto, puoi utilizzare App.Config
e le stringhe di connessione dalla tua configurazione dell'app:
var AppConfig = System.Configuration.ConfigurationManager.OpenExeConfiguration(@"bin\Debug\MyApp.exe");
Console.WriteLine($"Loaded {AppConfig.ConnectionStrings.ConnectionStrings.Count} connection strings");
In generale, è necessario implementare il metodo OnConfiguring nel tuo DbContext (qui per postgresql nel core 2.0):
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseNpgsql("Host=localhost; Database=mydb; User ID=myuser; Password=mypasswd; Port=0000; ");
}
OnConfiguring
è chiamato la prima volta che usi il contesto.
Avrei bisogno del tuo DbContext, per aiutarti di più.