31


私たちの組織は、単一データベース、マルチテナント(テナント ID ではなく、テーブル スキーマによる) アーキテクチャを持つ必要があります。

この種の作業を開始するための優れた記事がここにあります: http://romiller.com/2011/05/23/ef-4-1-multi-tenant-with-code-first/

記事の途中には、次のように書かれています。

お気付きのことと思いますが (おそらく少しがっかりしています)、エンティティごとにテーブル スキーマを構成するコードを記述する必要があります。確かに、このコードを気にかけている魔法のユニコーンは多くありません。EF の将来のバージョンでは、これをよりクリーンなカスタム規則に置き換えることができます。

私たちの目標は、同じモデルを持つ複数のスキーマに接続するために使用できる単一のコンテキスト クラスを持つ最もクリーンな方法を持つことです。
( modelBuilder.HasDefaultSchema は十分ではないように思われることに注意してください。これは、EF がコンテキストを初めて初期化し、OnModelCreating を実行するときにのみ適用されるためです)

前述のよりクリーンなカスタム規則は EF5 または EF6 に存在しますか?
または、これを何らかの形で処理するためのよりクリーンな方法はありますか?

注: EF の方向性に関連しているように思われるため、開発フォーラムでもこの質問をしましたが、ここに別の方法があるかどうかを確認したかったのです。

注 2: 移行については心配していません。個別に処理します。

4

4 に答える 4

2

非常に優れたアプローチであり、より簡単な解決策を得るのに役立ちました。Name-Method のみをオーバーライドできます。これはすべてのライターで使用されます....新しい回答で申し訳ありませんが、コメントすることはできません....

public class SqlServerSchemaAwareMigrationSqlGenerator:SqlServerMigrationSqlGenerator
{

    private string _schema;

    public accountMigrationSqlGenerator(string schema)
    {
        _schema = schema;
    }

    protected override string Name(string name)
    {

        int p = name.IndexOf('.');
        if(p>0)
        {
            name = name.Substring(p + 1);
        }

        return $"[{_schema}].[{name}]";

    }

}
于 2016-06-03T01:19:26.700 に答える
2

それが最初にコードではない場合は、次のようにします。

  • デフォルトのスキーマでテーブルを生成します。たとえば、dbo

  • 既存のデータベースに基づいて edmx を生成する

  • POCO を使用して EF を TT テンプレートの開始として使用する

  • TT ファイルを編集し、呼び出されたコンテキストに新しいプロパティを追加schemaして、生成されたクラスのクエリがデータベース オブジェクトにそれを使用するように強制します。

このようにして、さまざまなスキーマのコンテキストを作成し、オブジェクトがコンテキスト間を飛び回ることさえできるようになります。

于 2013-10-18T21:09:49.777 に答える
2

ありがとう:トビアス! あなたは私を何年も救ってくれます...

EF 6 での Oracle DB の変更:

public class IntegrationDbContext : DbContext, IDbModelCacheKeyProvider
{
    private static readonly ILog __log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

    /// <summary>
    /// Factory method
    /// </summary>
    public static IntegrationDbContext Create(string connectionStringName)
    {
        return new IntegrationDbContext(connectionStringName, GetDBSchema(connectionStringName));
    }

    /// <summary>
    /// Constructor
    /// </summary>
    public IntegrationDbContext()
    {
        Database.SetInitializer<IntegrationDbContext>(null);
    }

    /// <summary>
    /// Constructor
    /// </summary>
    internal IntegrationDbContext(string connectionString, string schemaName)
        : base("name={0}".Fill(connectionString))
    {
        Database.SetInitializer<IntegrationDbContext>(null);
        SchemaName = schemaName;
    }

    /// <summary>
    /// DB schema name
    /// </summary>
    public string SchemaName { get; private set; }

    #region Tables
    /// <summary>
    /// Integration table "SYNC_BONUS_DISTRIBUTION"
    /// </summary>
    public virtual DbSet<SYNC_BONUS_DISTRIBUTION> SYNC_BONUS_DISTRIBUTION { get; set; }

    /// <summary>
    /// Integration table "SYNC_MESSAGE_DISTRIBUTION"
    /// </summary>
    public virtual DbSet<SYNC_MESSAGE_DISTRIBUTION> SYNC_MESSAGE_DISTRIBUTION { get; set; }

    /// <summary>
    /// Integration table "IMPORT_TEMPLATES"
    /// </summary>
    public virtual DbSet<IMPORT_TEMPLATE> IMPORT_TEMPLATES { get; set; }

    #endregion //Tables

    private static Dictionary<string, string> __schemaCache = new Dictionary<string, string>();
    private static object __schCacheLock = new object();
    /// <summary>
    /// Gets DB schema name from connection string, or default from config
    /// </summary>
    private static string GetDBSchema(string connectionStringName)
    {
        string result;
        if (!__schemaCache.TryGetValue(connectionStringName, out result))
        {
            lock (__schCacheLock)
            {
                if (!__schemaCache.TryGetValue(connectionStringName, out result))
                {
                    DbConnectionStringBuilder builder = new DbConnectionStringBuilder();
                    builder.ConnectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;
                    result = builder.ContainsKey("User ID") ? builder["User ID"] as string : ConfigurationManager.AppSettings["DefaultIntegrationSchema"];
                    __schemaCache.Add(connectionStringName, result);
                }
            }
        }
        return result;
    }

    /// <summary>
    /// Context initialization
    /// </summary>
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        __log.DebugFormat("OnModelCreating for integration model in schema: {0}", SchemaName);
        if (SchemaName != null)
        {
            modelBuilder.HasDefaultSchema(SchemaName);
        }
        //### CLOB settings
        modelBuilder.Properties().Where(p => p.PropertyType == typeof(string) &&
                                             p.GetCustomAttributes(typeof(MaxLengthAttribute), false).Length == 0)
                                                .Configure(p => p.HasMaxLength(2000));

        base.OnModelCreating(modelBuilder);
    }

    /// <summary>
    /// Implementation of <see cref="IDbModelCacheKeyProvider.CacheKey"/> - thanks by this is 'OnModelCreating' calling for each specific schema.
    /// </summary>
    public string CacheKey
    {
        get { return SchemaName; }
    }
}
于 2016-11-04T10:05:44.690 に答える