1

エンティティ フレームワークに関するパズルに直面しています。mvc 4 とエンティティ フレームワーク 5.0 を使用して、次のテーブル名を持つ既存のアプリケーションへのアドオンを開発しています。

dbo.company1_contact
dbo.company1_product
dbo.company2_contact
dbo.company2_product

..

ユーザーは通常、会社 1 または会社 2 のいずれかにしかアクセスできず、すべての会社のユーザーをサポートしたいと考えています。これには、一般的なアプローチが必要です。

そこで、会社 1 用と会社 2 用に 2 つの edmx ファイルを作成し、同じエンティティ名とコンテキスト名を使用しました。次のようなクラスになります。

Entities.Company1.Contact
Entities.Company1.Product
Entities.Company2.Contact
Entities.Company2.Product

および 2 つのコンテキスト クラス:

Entities.Company1.Company1Entities
Entities.Company2.Company2Entities

たとえば、コントローラーには次のようなリポジトリ変数が必要になるため、これは一般的な方法で使用するには十分ではありません。

private Company1Entities db = new Company1Entities()

会社2の場合、これは次のようになります

private Company2Entities db = new Company2Entities()

一般的なアプローチは、インターフェイス ICompanyEntities とファクトリを使用して正しいリポジトリを取得することです。BUT - コンテキスト クラスに含まれる DbSet プロパティは同じ名前を持つ場合がありますが、同じ型ではありません。具体的には、たとえば、コンテキスト クラスで設定された製品は次のように定義されます。

DbSet<Entities.Company1.Product> Products  {}

DbSet<Entities.Company2.Product> Products  {}

そこで、T4 テンプレートを変更して、各タイプのインターフェイスを生成し、各エンティティにそのインターフェイスを実装させ、そのインターフェイスを持つ dbset を含む各コンテキスト クラスを生成します。

public interface IRepository {} 
public interface IContact {} 
public interface IProduct {} 

各企業について:

public class Product : IProduct {} 

そしてコンテキストクラスでは:

public class Company1Entities : DbContext, IRepository 
{
    ...

    public DbSet<IProduct> Products { get; set; }
    public DbSet<IContact> Contacts { get; set; }
}

これは問題なくコンパイルされ、問題が解決されることを願っていました。しかし、エンティティ フレームワークが大きな問題を引き起こしたため、完全に元に戻す必要がありました。

次に、db 変数に dynamic キーワードを使用しようとしましたが、linq はそれを受け入れません。誰かがこの問題を解決する方法を説明できますか? コントローラーをパーシャルとして記述し、db 変数を宣言する行のみを含む、会社ごとに 1 つのコントローラーを実装しない限り、これはエンティティ フレームワークでは不可能であると感じ始めています。これは私が本当にやりたくないことです。コントローラークラスを完全に複製したいと思います。解決策、一般的なアプローチはありますか? ここで何か不足していますか?助けていただければ幸いです。

4

2 に答える 2

1

どちらもまったく同じモデルであるため、両方に同じコンテキストを使用できます。顧客に応じて異なる方法でデータをロードするだけです。テーブル プレフィックスを示すコンストラクターの値を取得し、メソッドをオーバーライドして、OnModelCreatingそのプレフィックスをテーブル マッピングに設定します。

public class GenericEntities : DbContext, IRepository 
{
    //...

    private string TablePrefix { get; set; }

    public GenericEntities(string tablePrefix)
    {
        this.TablePrefix = tablePrefix;
    }

    public DbSet<Product> Products { get; set; }
    public DbSet<Contact> Contacts { get; set; }

    public override OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Product>.ToTable(TablePrefix + "_product");
        modelBuilder.Entity<Customer>.ToTable(TablePrefix + "_customer");
    }
}

重要な編集: 既定の構成では、アプリでの GenericEntities の最初の作成時にモデルがキャッシュされ、2 つのバージョンのモデルが作成されることはありません。これを回避する最も簡単な方法は、クライアントごとに GenericEntities のサブクラスを作成して、それぞれが個別にキャッシュされるようにすることです。多くのクライアントで長期的に使用する場合は、独自のキャッシング スキームを実装する必要があります (エンティティ クラス タイプではなくテーブル プレフィックスに基づく)。

public class Customer1Entities : GenericEntities
{
    public Customer1Entities() : base("customer1") {}
}

public class Customer2Entities : GenericEntities
{
    public Customer2Entities() : base("customer2") {}
}
于 2013-02-03T21:22:43.317 に答える
0

just.another.programmer からの回答は正しかったのですが、データベース ファーストを使用しているため、私の状況には当てはまりませんでした。代わりに、T4 を使用して一般的なエンティティを生成し、エンティティと会社ごとに次のようなコードを作成します。

IQueryable<GenericCustomer> Customers 
{
    get
    {
        return from c in db.Customers1
                select new GenericCustomer() 
                { Name = c.Name, ... }
    }
}

これで私の問題のほとんどが解決しました。

于 2013-02-04T22:03:39.767 に答える