代码之家  ›  专栏  ›  技术社区  ›  N. Carrer

c#interactive window(Oracle)中的实体框架代码优先

  •  0
  • N. Carrer  · 技术社区  · 7 年前

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

    我知道我需要传递连接字符串,因为交互窗口不会加载应用程序。配置文件,因此我重写了指定连接字符串的构造函数。

    我还必须说,我正在将Oracle数据库与ODP一起使用。网络提供商。

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

    #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#交互式窗口中工作?

    非常感谢。

    尼古拉

    2 回复  |  直到 7 年前
        1
  •  1
  •   N. Carrer    7 年前

    我终于设法让它工作了。

    首先,我收到消息“基础提供者在打开时失败”因为EF无法获得正确的提供程序和连接工厂。事实上,它试图使用SqlServer连接工厂,而不是Oracle的连接工厂。 在database first方法中,您可以从EntityConnection创建DbContext,EntityConnection指定提供者。不幸的是,在这种情况下,您似乎还必须提供模型,这不适用于代码。

    最后,我根据中的信息解决了提供者/工厂设置问题 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);
    };
    

    在这样做之后,我仍然得到以下错误: 无法确定“Oracle”类型的提供程序工厂的提供程序名称。ManagedDataAccess。客户OracleClientFactory”。确保ADO。NET provider已在应用程序配置中安装或注册。

    这是因为OracleClientFactory与实体框架提供者(来自“entityFramework”部分)没有关联。我无法直接从代码中执行此操作。最后,我将“entityFramework”部分添加到了我的机器中。配置:

    <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>
    

        2
  •  0
  •   greyxit    7 年前

    首先,你可以使用 App.Config 以及应用程序配置中的连接字符串:

    var AppConfig = System.Configuration.ConfigurationManager.OpenExeConfiguration(@"bin\Debug\MyApp.exe");
    Console.WriteLine($"Loaded {AppConfig.ConnectionStrings.ConnectionStrings.Count} connection strings");
    

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseNpgsql("Host=localhost; Database=mydb; User ID=myuser; Password=mypasswd; Port=0000; ");
    }
    

    OnConfiguring 第一次使用上下文时调用。