关键“数据源”的值长度超过了'128'的限制

时间:2016-05-17 16:49:04

标签: c# oracle ef-code-first entity-framework-6 connection-string

我知道有一个非常类似的问题被问到here,但答案对我没有帮助。

我正在使用Entity Framework 6和Oracle.ManagerDataAccess.Client。

如果我在app.config中定义连接字符串,则连接有效。 如果我在代码中指定相同的连接字符串,那么我得到错误

The value's length for key 'data source' exceeds it's limit of '128'.

这是正确的。

这是我的连接字符串(删除了一些名称):

"User Id=xxxxxxxxxxx;Password=xxxx;Data Source=( DESCRIPTION = ( ADDRESS_LIST = ( ADDRESS = (PROTOCOL = TCP)(HOST = VS-ORACLE.xxxxxxx.de)(PORT = 1521) ) ) ( CONNECT_DATA = (SERVER = DEDICATED)(SERVICE_NAME = orcl.xxxxxxxx.de) ) )"

我知道有一堆空格可以删除,但我仍然不会将字符串缩小到128个字符以下。

当连接字符串在app.config中时它是如何工作的,但是当它在代码中时呢?

通过将一些参数卸载到另一个字符串,有什么技巧可以使用吗?

我已经在使用DBConfiguration对象了。有没有办法在该对象中设置一些参数?

如果我使用完整的oracle客户端,我想我可以在文件tnsnames.ora中引用一个配置,但如果我们可以在没有完整客户端的情况下与oracle数据库通信,那将是一个很好的奖励。

更新

这是app.config

中连接字符串的样子
<connectionStrings>
  <add name="OracleDbContext" providerName="Oracle.ManagedDataAccess.Client" connectionString="User Id=xxxxxxxxxxx;Password=xxxx;Data Source=( DESCRIPTION = ( ADDRESS_LIST = ( ADDRESS = (PROTOCOL = TCP)(HOST = VS-ORACLE.xxxxxxxx.de)(PORT = 1521) ) ) ( CONNECT_DATA = (SERVER = DEDICATED)(SERVICE_NAME = orcl.xxxxxxxx.de) ) )" />
</connectionStrings>

在代码中我已经定义了上下文类:

[DbConfigurationType(typeof(OracleDBConfiguration))]
public class GlobalAttributeContext : DbContext
{
  public DbSet<GlobalAttribute>  GlobalAttributes { get; set; }

  static GlobalAttributeContext()
  {
    Database.SetInitializer<GlobalAttributeContext>(null);
  }

  public GlobalAttributeContext(string nameOrConnectionString) : base(nameOrConnectionString)
  {
  }

  public GlobalAttributeContext() : this ( "Name=OracleDbContext" )
  {
  }

  protected override void OnModelCreating(DbModelBuilder modelBuilder)
  {
    // We have to pass the schema name into the configuration. (Is there a better way?)
    modelBuilder.Configurations.Add(new GlobalAttribute_Config_Oracle("SchemaName")) ;
  }
}

我已经定义了一个DbConfiguration类,如下所示:

class OracleDBConfiguration : DbConfiguration
{
  public OracleDBConfiguration()
  {
    this.SetDefaultConnectionFactory ( new System.Data.Entity.Infrastructure.LocalDbConnectionFactory("v12.0") ) ;
    this.SetProviderServices ( "Oracle.ManagedDataAccess.Client", Oracle.ManagedDataAccess.EntityFramework.EFOracleProviderServices.Instance ) ;
    this.SetProviderFactory  ( "Oracle.ManagedDataAccess.Client", Oracle.ManagedDataAccess.Client.OracleClientFactory.Instance ) ;
  }
}

最后,我创建了像这样的上下文

string ConnectionString = "User Id=xxxxxxxxxxx;Password=xxxx;Data Source=( DESCRIPTION = ( ADDRESS_LIST = ( ADDRESS = (PROTOCOL = TCP)(HOST = VS-ORACLE.xxxxxxxx.de)(PORT = 1521) ) ) ( CONNECT_DATA = (SERVER = DEDICATED)(SERVICE_NAME = orcl.xxxxxxx.de) ) )" ;

using (var ctx = new GlobalAttributeContext(ConnectionString))
{
  var globalAttributes = ctx.GlobalAttributes.ToList() ;
  foreach ( GlobalAttribute ga in globalAttributes )
  {
    Console.WriteLine ( "Name: {0}, Value: {1}", ga.Attribute, ga.Value ) ;
  }
}

两种方法中使用的连接字符串是相同的。

3 个答案:

答案 0 :(得分:1)

我的同事已经找到了这个问题的答案如下:

将另一个构造函数添加到上下文类以使用现有集合。

public GlobalAttributeContext(DbConnection existingConnection, bool contextOwnsConnection) 
       : base(existingConnection, true)
{
}

这是完整的上下文类

namespace OracleTestExeConfigAndConnStr
{
  [DbConfigurationType(typeof(OracleDBConfiguration))]
  public class GlobalAttributeContext : DbContext
  {
    public DbSet<GlobalAttribute>  GlobalAttributes { get; set; }

    static GlobalAttributeContext()
    {
      Database.SetInitializer<GlobalAttributeContext>(null);
    }

    public GlobalAttributeContext() : base("OracleDbContext")
    {
    }

    public GlobalAttributeContext(string nameOrConnectionString)
           : base(nameOrConnectionString)
    {
    }

    public GlobalAttributeContext(DbConnection existingConnection, bool contextOwnsConnection)
           : base(existingConnection, true)
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
      // We have to pass the schema name into the configuration. (Is there a better way?)
      modelBuilder.Configurations.Add(new GlobalAttribute_Config_Oracle("SchemaName")) ;
    }
  }
}

单独创建数据库连接,并将连接传递给上下文对象。

string connStr = @"User Id=xxxxxxxxxxx;Password=xxxx;Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=VS-ORACLE.xxxxxxxx.de)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=orcl.xxxxxxxx.de)))";

using (var connection = new OracleConnection() { ConnectionString = connStr })
{
  connection.Open();
  using (var ctx = new GlobalAttributeContext(connection, true))
  {
    var globalAttributes = ctx.GlobalAttributes.ToList();
    foreach (GlobalAttribute ga in globalAttributes)
    {
      Console.WriteLine("Name: {0}, Value: {1}", ga.Attribute, ga.Value);
    }
  }
}

为了完整性,这是DBConfiguration类,它被指定为上下文类的属性。

class OracleDBConfiguration : DbConfiguration
{
  public OracleDBConfiguration()
  {
    this.SetDefaultConnectionFactory ( new System.Data.Entity.Infrastructure.LocalDbConnectionFactory("v12.0") ) ;
    this.SetProviderServices ( "Oracle.ManagedDataAccess.Client", Oracle.ManagedDataAccess.EntityFramework.EFOracleProviderServices.Instance ) ;
    this.SetProviderFactory  ( "Oracle.ManagedDataAccess.Client", Oracle.ManagedDataAccess.Client.OracleClientFactory.Instance ) ;
  }
}

此方法适用于DLL,不需要app.config中的任何值。

答案 1 :(得分:0)

您不需要任何Oracle客户端来使用tnsnames.ora文件。

请参阅this answer(最后一段)ODP.NET托管驱动程序期望tnsnames.ora的文件夹。 sqlnet.ora个文件。

您也可以在.config文件中定义别名,请参阅Configuring Oracle Data Provider for .NET

答案 2 :(得分:0)

一旦我没有足够的声誉来评论任何问题或答案,我就会在这里发布我的发现。

就我而言,Phill Jollans 的回答几乎解决了。下面的细节必须另外做

  • 我不需要那么多构造函数;在上下文类中,只有接收连接字符串并将其传递给基类的构造函数就足够了。
  • 我必须手动删除 app.config 文件中的 SqlServer 连接字符串提供程序。

很可能是上下文试图实例化与 SqlServer 而不是 Oracle 的连接,导致该验证抛出此异常。 oracle数据源key好像没有这个限制。