简体   繁体   中英

Using SqlConnectionStringBuilder for EF connection string throws exception

I have this small method which should create a custom object called DataSource :

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

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

    return dbConnection;
}

The main reason I use this class ( SqlConnectionStringBuilder ) is to comfortably grab the catalog and data source.

When I pass an Entity Framework connection string to it (and initialize the SqlConnectionStringBuilder ), I get the following exception:

Keyword not supported: 'metadata'

I could start analyzing the string to check and differentiate between Entity Framework connection string and classic one, but really want something elegant to address them both without the code having to "know" about it (because I iterate many kinds of them in my project).

Here is the connection string example which fails:

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

This error does not happen in classic connection strings like :

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

Suggestions for something elegant to grab both kinds of connection strings? Is there something else except SqlConnectionStringBuilder that I can use? Maybe I should truncate some redundant string and strip it away from the Entity Framework connection string before I try to build it?

Thanks in advance .

I have been using this method created by myself. Maybe it's not the most elegant solution, but it works:

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

You can use this filtered connectionString to create a SqlConnectionStringBuilder, or modify this method to extract the datasource and initial catalog.

I eventually used both of the offered solutions here combined . marc_s suggested using the class EntityConnectionStringBuilder and Alenjandro suggested checking the provider to determine if it's EF . EntityConnectionStringBuilder cannot parse regular System.Data.SqlClient so :

        ...
        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;
    }

In the EntityConnectionStringBuilder i found the property ProviderConnectionString which is exactly what the SqlConnectionStringBuilder class expect as a valid connection string value to parse , so besides that extra if (which i hate) the code behaves almost the same .

Thanks for the answers !

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM