DbProviderFactory
toschug opened this issue · comments
Your blog post about DbProviderFactory
brought me here as I am trying to get a lib to .NET Standard.
After some (unsuccesful) testing:
Is it possible, that there is some kind of variable "mismatch" in DataUtils.GetDbProviderFactory
regarding providername
and providerName
?
The exception I get is:
System.NotSupportedException: 'Unsupported Provider Factory specified: System.Data.SqlClient'
I replaced providername
/providerName
with _lower
to make it clearer what I mean:
public static DbProviderFactory GetDbProviderFactory(string providerName)
{
#if NETFULL
return DbProviderFactories.GetFactory(providerName);
#else
var _lower = providerName.ToLower();
if (_lower == "system.data.sqlclient")
return GetDbProviderFactory(DataAccessProviderTypes.SqlServer);
if (_lower == "system.data.sqlite" || _lower == "microsoft.data.sqlite")
return GetDbProviderFactory(DataAccessProviderTypes.SqLite);
if (_lower == "mysql.data.mysqlclient" || _lower == "mysql.data")
return GetDbProviderFactory(DataAccessProviderTypes.MySql);
if (_lower == "npgsql")
return GetDbProviderFactory(DataAccessProviderTypes.PostgreSql);
throw new NotSupportedException(string.Format(Resources.UnsupportedProviderFactory,providerName));
#endif
}
For now I ripped off this bit into "my" lib for a first workaround (and to see that it could be that mismatch):
DbProviderFactory GetFactory(string providerName)
{
var _lower = providerName.ToLower();
if (_lower == "system.data.sqlclient")
return SqlClientFactory.Instance;
return null;
}
I hope it is some help and that I don't misunderstand something completly.
Thanks anyway (and for the blog post ;) )
Make sure you have a reference added to System.Data.SqlClient? It should be there if you're using this library but if you use your own code you have to make sure you add the dependency to your project.
I am aware of this, but thanks for pointing this out.
I even added System.Data.SqlClient
explicit although it gets already referenced by WestWind.Utilities.
Same exception.
What I am trying to say is that when I pass the string parameter "System.Data.SqlClient"
to DataUtils.GetDbProviderFactory
then it will run straight into the NotSupportedException
.
First, the value of providerName
(with uppercase N in name) gets converted to lower case and assigned to providername
(wither lowercase n in name). Later on the uppercase variant (providerName
) gets checked against the lowercase hardcoded strings (like "system.data.sqlclient"
). So it can never evaluate to true and thus falls through to the Exception. The only time when it should work is against MySql.Data
/mysql.data
.
I hope it explains it better what I mean, sorry for confusion.
Excerpt from master branch (https://raw.githubusercontent.com/RickStrahl/Westwind.Utilities/master/Westwind.Utilities/Utilities/DataUtils.cs) with some comments (UPPERCASE
/ LOWERCASE
):
// UPPERCASE
public static DbProviderFactory GetDbProviderFactory(string providerName)
{
#if NETFULL
return DbProviderFactories.GetFactory(providerName);
#else
// LOWERCASE
var providername = providerName.ToLower();
// UPPERCASE <-> LOWERCASE -> always false
if (providerName == "system.data.sqlclient")
return GetDbProviderFactory(DataAccessProviderTypes.SqlServer);
if (providerName == "system.data.sqlite" || providerName == "microsoft.data.sqlite")
return GetDbProviderFactory(DataAccessProviderTypes.SqLite);
// LOWERCASE<->LOWERCASE -> true!
if (providerName == "mysql.data.mysqlclient" || providername == "mysql.data")
return GetDbProviderFactory(DataAccessProviderTypes.MySql);
if (providerName == "npgsql")
return GetDbProviderFactory(DataAccessProviderTypes.PostgreSql);
throw new NotSupportedException(string.Format(Resources.UnsupportedProviderFactory,providerName));
#endif
}
I ran into this same problem just a moment ago, looked at the source and noticed the same issue. I was about to write up a ticket and it looks like @toschug beat me by a couple days. You're converting the providerName
to lower case as providername
and then using the unconverted providerName
parameter passed to the method to compare against your lower case strings in most of the conditions.
I'd recommend using the string Equals with the IgnoreCase option rather than converting your string, as well.
public static DbProviderFactory GetDbProviderFactory(string providerName)
{
#if NETFULL
return DbProviderFactories.GetFactory(providerName);
#else
if (providerName.Equals("system.data.sqlclient", StringComparison.OrdinalIgnoreCase))
return GetDbProviderFactory(DataAccessProviderTypes.SqlServer);
if (providerName.Equals("system.data.sqlite", StringComparison.OrdinalIgnoreCase) ||
providerName.Equals("microsoft.data.sqlite", StringComparison.OrdinalIgnoreCase))
return GetDbProviderFactory(DataAccessProviderTypes.SqLite);
if (providerName.Equals("mysql.data.mysqlclient", StringComparison.OrdinalIgnoreCase) ||
providerName.Equals("mysql.data", StringComparison.OrdinalIgnoreCase))
return GetDbProviderFactory(DataAccessProviderTypes.MySql);
if (providerName.Equals("npgsql", StringComparison.OrdinalIgnoreCase))
return GetDbProviderFactory(DataAccessProviderTypes.PostgreSql);
throw new NotSupportedException(string.Format(Resources.UnsupportedProviderFactory,providerName));
#endif
}
Thanks for the catch on this... I made the fix comparing to the proper string. Duh :-)
I avoided individual Equals calls because there are a lot of them to avoid overhead of many comparisons. Probably negligible but old habits and all...