Entity framework C# 交互中的代码优先 window (Oracle)
Entity framework Code-First in c# interactive window (Oracle)
我正在尝试使用 c# 交互式 window 来快速测试我的一些代码。
当我尝试测试与 DbContext (EF6) 相关的代码时,我 运行 遇到了麻烦。
我知道我需要传递连接字符串,因为交互式 window 不会加载 App.config 文件,所以我覆盖了指定连接字符串的构造函数。
我还要说的是,我正在使用 Oracle 数据库和 ODP.NET 提供程序。
这是我尝试 运行 在交互式 window:
上的代码
#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()
这是我得到的例外情况
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>)
我的 DbContext 看起来像这样:
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);
}
}
我认为原因是我无法指定正确的提供商。有人成功地使用代码优先 EntityFramework 代码(在 oracle 上)从 c# interactive window 工作吗?
非常感谢。
尼古拉
首先,您可以使用 App.Config
和应用配置中的连接字符串:
var AppConfig = System.Configuration.ConfigurationManager.OpenExeConfiguration(@"bin\Debug\MyApp.exe");
Console.WriteLine($"Loaded {AppConfig.ConnectionStrings.ConnectionStrings.Count} connection strings");
一般来说,你需要在你的 DbContext 中实现 OnConfiguring 方法(这里是针对核心 2.0 中的 postgresql):
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseNpgsql("Host=localhost; Database=mydb; User ID=myuser; Password=mypasswd; Port=0000; ");
}
OnConfiguring
在您第一次使用上下文时被调用。
我需要你的 DbContext 来帮助你。
我终于成功了。
首先,我收到消息 "The underlying provider failed on Open.",因为 EF 无法获得正确的提供程序和连接工厂。它实际上是在尝试使用 SqlServer 连接工厂而不是来自 Oracle 的连接工厂。
在数据库优先的方法中,您可以从指定提供程序的 EntityConnection 创建 DbContext。不幸的是,在这种情况下,您似乎还必须提供不适用于代码优先的模型。
最后我按照 this post 中的信息解决了 provider/factory 设置。
对应的csx代码为:
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);
};
这样做之后我仍然得到以下错误:
无法确定 'Oracle.ManagedDataAccess.Client.OracleClientFactory' 类型的提供程序工厂的提供程序名称。确保 ADO.NET 提供程序已安装或在应用程序配置中注册。
这是因为 OracleClientFactory 未关联到 entity framework 提供程序(来自 "entityFramework" 部分)。我无法直接从代码中执行此操作。我最终将 "entityFramework" 部分添加到我的 machine.config:
configSections 声明:
<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" />
配置部分内容:
<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>
有了这些配置,我终于能够在 c# 交互中使用我的 Oracle 代码优先 EF6 代码 window。
我正在尝试使用 c# 交互式 window 来快速测试我的一些代码。 当我尝试测试与 DbContext (EF6) 相关的代码时,我 运行 遇到了麻烦。
我知道我需要传递连接字符串,因为交互式 window 不会加载 App.config 文件,所以我覆盖了指定连接字符串的构造函数。
我还要说的是,我正在使用 Oracle 数据库和 ODP.NET 提供程序。
这是我尝试 运行 在交互式 window:
上的代码#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()
这是我得到的例外情况
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>)
我的 DbContext 看起来像这样:
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);
}
}
我认为原因是我无法指定正确的提供商。有人成功地使用代码优先 EntityFramework 代码(在 oracle 上)从 c# interactive window 工作吗?
非常感谢。
尼古拉
首先,您可以使用 App.Config
和应用配置中的连接字符串:
var AppConfig = System.Configuration.ConfigurationManager.OpenExeConfiguration(@"bin\Debug\MyApp.exe");
Console.WriteLine($"Loaded {AppConfig.ConnectionStrings.ConnectionStrings.Count} connection strings");
一般来说,你需要在你的 DbContext 中实现 OnConfiguring 方法(这里是针对核心 2.0 中的 postgresql):
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseNpgsql("Host=localhost; Database=mydb; User ID=myuser; Password=mypasswd; Port=0000; ");
}
OnConfiguring
在您第一次使用上下文时被调用。
我需要你的 DbContext 来帮助你。
我终于成功了。
首先,我收到消息 "The underlying provider failed on Open.",因为 EF 无法获得正确的提供程序和连接工厂。它实际上是在尝试使用 SqlServer 连接工厂而不是来自 Oracle 的连接工厂。 在数据库优先的方法中,您可以从指定提供程序的 EntityConnection 创建 DbContext。不幸的是,在这种情况下,您似乎还必须提供不适用于代码优先的模型。
最后我按照 this post 中的信息解决了 provider/factory 设置。 对应的csx代码为:
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);
};
这样做之后我仍然得到以下错误: 无法确定 'Oracle.ManagedDataAccess.Client.OracleClientFactory' 类型的提供程序工厂的提供程序名称。确保 ADO.NET 提供程序已安装或在应用程序配置中注册。
这是因为 OracleClientFactory 未关联到 entity framework 提供程序(来自 "entityFramework" 部分)。我无法直接从代码中执行此操作。我最终将 "entityFramework" 部分添加到我的 machine.config:
configSections 声明:
<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" />
配置部分内容:
<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>
有了这些配置,我终于能够在 c# 交互中使用我的 Oracle 代码优先 EF6 代码 window。