Questo post è più una nota personale che vorrei condividere a fronte delle diverse volte in cui ho riscontrato questa esigenza.
Quando si effettua il deploy di un’ applicazione che utilizza EF su System.Data.SQLite, è possibile trovarsi di fronte al seguente errore:
[ArgumentException: Impossibile trovare il provider dati .Net Framework richiesto. Potrebbe non essere installato.]
System.Data.Common.DbProviderFactories.GetFactory(String providerInvariantName) +1310319
System.Data.EntityClient.EntityConnection.GetFactory(String providerString) +35
[ArgumentException: Il provider dell'archivio specificato non è stato trovato nella configurazione oppure non è valido.]
System.Data.EntityClient.EntityConnection.GetFactory(String providerString) +62
System.Data.EntityClient.EntityConnection.ChangeConnectionString(String newConnectionString) +394
System.Data.EntityClient.EntityConnection..ctor(String connectionString) +82
System.Data.Objects.ObjectContext.CreateEntityConnection(String connectionString) +42
System.Data.Objects.ObjectContext..ctor(String connectionString, String defaultContainerName) +16
...
|
Solitamente, la causa risiede nella mancata registrazione del provider System.Data.SQLite a livello di machine.config della macchina. La classica soluzione prevede quindi la registrazione esplicita del provider a livello applicazione sfruttando il .config (Riferimento MSDN: http://msdn.microsoft.com/en-us/library/dd0w4a2z(VS.80).aspx):
<configuration>
<system.data>
<DbProviderFactories>
<remove invariant="System.Data.SQLite"/>
<add name="SQLite Data Provider" invariant="System.Data.SQLite"
description=".Net Framework Data Provider for SQLite"
type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
</DbProviderFactories>
</system.data>
</configuration>
Tuttavia, in soluzioni in cui si richiede che il DbProviderFactory sia caricato on-demand a runtime (ad esempio in sistemi che utilizzano IoC per l’accesso ai dati) si potrebbe ricorrere alla seguente tecnica: enumerare i DbProviderFactory correntemente installati e, qualora System.Data.SQLite non fosse trovato, caricarlo esplicitamente:
DataTable factoryClassesTable = System.Data.Common.DbProviderFactories.GetFactoryClasses();
IEnumerable<DataRow> queryResult = from factoryClassDataRow in factoryClassesTable.AsEnumerable()
where factoryClassDataRow.Field<string>("InvariantName") == "System.Data.SQLite"
select factoryClassDataRow;
if (queryResult.Count() == 0)
{
System.Data.DataSet dataSet = ConfigurationManager.GetSection("system.data") as System.Data.DataSet;
if (dataSet != null) dataSet.Tables[0].Rows.Add("SQLite Data Provider", ".Net Framework Data Provider for SQLite",
"System.Data.SQLite",
"System.Data.SQLite.SQLiteFactory, System.Data.SQLite");
}
Ovviamente ogni ulteriore considerazione è ben accetta :D