39

(Entity Framework に基づく) データ層で DbProviderFactories を使用しており、データベースに SQLite を使用していますが、App.Config を使用して次のコードを作成する必要はありません。

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

代わりに、データレイヤーにプログラムでそれを入れたいと思います。誰でもこれを行う方法を知っていますか?

編集:

この理由は、IoC コンテナーを使用してデータ レイヤーを選択していて、データ レイヤーの一部が App.Config 値を必要としないか、データ レイヤーに強く結び付けられているためです。

4

8 に答える 8

57

以下はおそらく黒点を引き起こし、西洋文明を転覆させます。ダクトテーププログラミングについての議論を引き起こす可能性さえありますが(やめさせてください!)、しかし(今のところ)うまくいきます

try
{
    var dataSet = ConfigurationManager.GetSection("system.data") as System.Data.DataSet;
    dataSet.Tables[0].Rows.Add("SQLite Data Provider"
    , ".Net Framework Data Provider for SQLite"
    , "System.Data.SQLite"
    , "System.Data.SQLite.SQLiteFactory, System.Data.SQLite");
}
catch (System.Data.ConstraintException) { }
于 2009-11-04T00:00:32.570 に答える
6

上記の JoshRivers は、SQLite のソリューションを投稿しました。これは実際、他のアダプターにも使用できます。彼の例を使用して、MySQL で動作させることができました。これをもう少し一般的なものにラップしました。これは、アプリケーションの起動時に実行する必要があり、.NET コネクタ バージョン 6.6.5.0 用です (ただし、他のバージョンにも適していると思います)。

string dataProvider = @"MySql.Data.MySqlClient";
string dataProviderDescription = @".Net Framework Data Provider for MySQL";
string dataProviderName = @"MySQL Data Provider";
string dataProviderType = @"MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.6.5.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d";

bool addProvider = true;
var dataSet = ConfigurationManager.GetSection("system.data") as DataSet;
foreach (DataRow row in dataSet.Tables[0].Rows)
{
    if ((row["InvariantName"] as string) == dataProvider)
    {
        // it is already in the config, no need to add.
        addProvider = false;
        break;
    }
}

if (addProvider)
    dataSet.Tables[0].Rows.Add(dataProviderName, dataProviderDescription, dataProvider, dataProviderType);
于 2013-12-19T00:34:41.037 に答える
3

EF 6.0 以降の更新プログラム

DbProviderFactoryaを登録IDbDependencyResolverして type を解決することで、a を追加できますDbProviderFactory。この例を以下に示します。

static class Program
{
    [STAThread]
    static void Main()
    {
        System.Data.Entity.DbConfiguration.Loaded += (_, a) => {
            a.AddDependencyResolver(new MyDependencyResolver(), true);
        };  

        Application.Run(new Form1());
    }
}

class MyDependencyResolver : System.Data.Entity.Infrastructure.DependencyResolution.IDbDependencyResolver {

    public object GetService(Type type, object key) {

        // Output the service attempting to be resolved along with it's key 
        System.Diagnostics.Debug.WriteLine(string.Format("MyDependencyResolver.GetService({0}, {1})", type.Name, key == null ? "" : key.ToString()));

        if (type == typeof(System.Data.Common.DbProviderFactory)) {

            // Return whatever DbProviderFactory is relevant
            return new MyDbProviderFactory(); 

        }else if(type == typeof(System.Data.Entity.Infrastructure.IProviderInvariantName) && key != null && key == "MyDbProviderFactory"){

            // Return the Provider's invariant name for the MyDbProviderFactory
            return new MyProviderInvariantName();

        }

        return null;
    }

    public IEnumerable<object> GetServices(Type type, object key) {
        return new object[] { GetService(type, key) }.ToList().Where(o => o != null);
    }
}

必要なオーバーライドのタイプとプロジェクトのセットアップ方法に応じて、いくつかの追加のタイプを解決する必要がある場合があります。基本的には、上記のコードから始めて、特定の要件に対して解決する必要があるすべてのサービスを決定するまでデバッグを続けます。

EF の依存関係の解決の詳細については、以下のリンクを参照してください。

DbConfigurationさらに、上記の最初のリンクで説明されているようにオーバーライドすることで、この構成を行うことができます。

于 2014-08-25T16:12:49.233 に答える
3

遅い回答:

次のようなファクトリをいつでも直接取得できます。

DbProviderFactory factory = System.Data.SQLite.SQLiteFactory.Instance;
// (note that the rest of the code is still provider-agnostic.)

または、IoC コンテナーを使用して、次のように解決しますDbProviderFactory

container.RegisterInstance<DbProviderFactory>(SQLiteFactory.Instance);

構成ファイル(または@ JoshRiverの回答のようなハック)を必要とするという制限があるため、使用しないことを好みます。DbProviderFactories.GetFactory

プロバイダー名を使用して登録済みのファクトリ型のアセンブリ修飾名DbProviderFactories.GetFactoryを検索し、リフレクションを使用して静的プロパティの値を取得します。Instance

構成を使用したくない場合は、ユース ケースによっては上記のいずれかの方法が便利な場合があります。

于 2013-11-02T09:59:02.783 に答える
2

DB プロバイダー ファクトリをプログラムで選択すると、ほとんど目的が達成できなくなります。これらすべてのインターフェイスの代わりに、SQLite に固有のクラスを使用することもできますよね?

于 2009-07-13T04:31:12.220 に答える
0

次のスニペットを参照してください

    public DataProviderManager(string ProviderName)
    {

       var  _Provider = DbProviderFactories.GetFactory(ProviderName);

    }

あなたの場合は「System.Data.SQLite」であるProviderNameを渡す必要があります。

アプリ設定セクションを作成する必要はありません。このセクションは、SQLite.netプロバイダーがインストールされた後、machine.configのSQLiteによって作成されます。

appconfigセクションの全体的な目的は、次のコマンドを呼び出したときに、構成された.netプロバイダーのリストを取得できるようにすることです。

public GetProvidersList(){DataTable table = DbProviderFactories.GetFactoryClasses(); }

于 2011-05-04T20:25:28.693 に答える