使用SqlConnectionStringBuilder进行EF连接字符串抛出异常

时间:2017-05-15 12:33:08

标签: c# .net entity-framework connection-string

我有这个小方法应该创建一个名为DataSource的自定义对象:

private static DataSource BuildDataSourceFromString(string connectionString)
{
    SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectionString);

    DataSource dbConnection = new DataSource()
        {
            Source = builder.DataSource,
            Catalog = builder.InitialCatalog
        };

    return dbConnection;
}

我使用此类(SqlConnectionStringBuilder)的主要原因是可以轻松获取目录和数据源。

当我向其传递Entity Framework连接字符串(并初始化SqlConnectionStringBuilder)时,我得到以下异常:

  

不支持关键字:'元数据'

我可以开始分析字符串来检查和区分实体框架连接字符串和经典字符串,但是真的想要一些优雅的东西来解决它们,而不需要代码知道"知道"关于它(因为我在我的项目中迭代了很多种类)。

以下是失败的连接字符串示例:

<add name="someconnectionstring" 
     connectionString="metadata=res://*/DB.SomeDataModel.csdl|res://*/DB.SomeDataModel.ssdl|res://*/DB.SomeDataModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=some-data-source;initial catalog=SomeCatalog;integrated security=True;MultipleActiveResultSets=True;MultiSubnetFailover=True;App=EntityFramework&quot;" 
     providerName="System.Data.EntityClient" />

在经典连接字符串中不会发生此错误,例如:

<connectionStrings>
    <add name="SomeData" 
         connectionString="Server=Some-Server;Database=SomeCatalog;Integrated Security=SSPI;"
         providerName="System.Data.sqlclient"  />
</connectionStrings>

建议优雅地抓取两种连接字符串?我可以使用除SqlConnectionStringBuilder之外的其他内容吗?也许我应该截断一些冗余字符串并在我尝试构建之前将其从Entity Framework连接字符串中删除?

提前致谢。

2 个答案:

答案 0 :(得分:1)

我一直在使用自己创建的这个方法。也许它不是最优雅的解决方案,但它确实有效:

private static string FilterConnectionString(string connectionStringEntity, bool useProvider = true)
        {
            string result = "";
            string[] split = connectionStringEntity.Split(new char[2] { ';', '"' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (var item1 in split)
            {
                string item = item1.Trim();
                if (item.ToLower().StartsWith("data source") ||
                   item.ToLower().StartsWith("initial catalog") ||
                   item.ToLower().StartsWith("user id") ||
                   item.ToLower().StartsWith("password") ||
                   item.ToLower().StartsWith("multipleactiveresultSets"))
                    result += item + ";";
            }
            return useProvider ? result + "provider=System.Data.SqlClient" : result;
        }

您可以使用此过滤的connectionString创建SqlConnectionStringBuilder,或修改此方法以提取数据源和初始目录。

答案 1 :(得分:0)

我最终结合使用了两种提供的解决方案。  marc_s建议使用EntityConnectionStringBuilder类,Alenjandro建议检查提供者以确定它是否为EF。 EntityConnectionStringBuilder无法解析常规的System.Data.SqlClient,所以:

        ...
        XAttribute provider = connectionStringElement.Attribute("providerName");
        string providerValue = provider == null ? string.Empty : provider.Value;

        bool isEntityFramework = providerValue.Equals("System.Data.EntityClient");
        dbConn = BuildDataSourceFromString(connectionStringValue, isEntityFramework);
        if (dbConn == null)
        {
            return;
        }

        connectionStrings.Add(dbConn);
    }
    private static DataSource BuildDataSourceFromString(string connectionString, bool isEntityFramework)
    {
        log.InfoFormat("Is connection string entity framework ? {0}",  isEntityFramework.ToString());
        if (isEntityFramework)
        {
            EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder(connectionString);
            connectionString = entityBuilder.ProviderConnectionString;
        }

        SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(connectionString);


        DataSource dbConnection = new DataSource()
        {
            Source = builder.DataSource,
            Catalog = builder.InitialCatalog
        };
        return dbConnection;
    }

在EntityConnectionStringBuilder中,我找到了属性ProviderConnectionString,这正是SqlConnectionStringBuilder类期望作为要解析的有效连接字符串值所期望的,所以除了额外的if(我讨厌)之外,代码的行为几乎相同。 / p>

感谢您的回答!