实体框架C#交互式窗口中的Code-First(Oracle)

时间:2017-11-03 09:00:54

标签: c# oracle entity-framework entity-framework-6 c#-interactive

我试图使用c#交互式窗口快速测试我的一些代码。 当我尝试测试与DbContext(EF6)相关的代码时,我遇到了麻烦。

我知道我需要传递连接字符串,因为交互式窗口不会加载App.config文件,所以我重写了指定连接字符串的构造函数。

我还要说我正在使用Oracle数据库和ODP.NET提供程序。

以下是我试图在交互式窗口上运行的代码:

#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);
    }
}

我认为原因是我无法指定正确的提供商。有人设法在c#交互窗口中使用代码优先的EntityFramework代码(在oracle上)吗?

非常感谢提前。

尼古拉

2 个答案:

答案 0 :(得分:1)

我终于成功了。

首先,我收到了消息&#34;基础提供商在Open上失败了。&#34;因为EF无法获得正确的提供商和连接工厂。事实上,尝试使用SqlServer连接工厂而不是Oracle工厂。 在数据库优先方法中,您可以从EntityConnection创建DbContext,它指定提供者。不幸的是,似乎在这种情况下你必须提供模型,这不适用于代码优先。

最后,我在this post的信息后面解决了提供商/工厂设置问题。 相应的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);
};

完成后我仍然遇到以下错误: 无法确定类型&#39; Oracle.ManagedDataAccess.Client.OracleClientFactory&#39;的提供程序工厂的提供程序名称。确保在应用程序配置中安装或注册了ADO.NET提供程序。

这是因为OracleClientFactory没有与实体框架提供者相关联(来自&#34; entityFramework&#34;部分)。我无法直接从代码中执行此操作。我最终添加了&#34; entityFramework&#34;部分到我的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" />

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>

有了这些配置,我终于可以在c#交互窗口中使用我的Oracle代码优先EF6代码了。

答案 1 :(得分:0)

首先,您可以使用应用配置中的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,以帮助你更多。