簡體   English   中英

實體框架和在單個上下文中具有多個模式的遷移

[英]Entity Framework and Migration with multiple schemas in a single Context

我正在使用Entity Framework Code First開發一個多租戶應用程序。 每個租戶在數據庫中都有不同的模式,但應用程序將為所有租戶提供單個上下文和模型。

Entity Framwork 6能夠在同一個數據庫中使用多個具有多個上下文的模式,但是我沒有找到一種方法來使用單個上下文的多個模式。

我已經(通過命令行)生成了對默認“dbo”架構的遷移。 我想使用這些遷移更新其他模式。

雖然我同意多個上下文絕對是更好的方法(並且我是如何設置自己的項目),但我想回答一下如何在單個上下文中使用多個模式的原始問題:

在每個模型的映射配置中,您可以調用'ToTable(myTableName,mySchema)'來修改表所屬的模式:

public class MyEntityMap : EntityTypeConfiguration<MyEntity>
{
    public MyEntityMap ()
    {
        HasKey(t => t.MyId);
        Property(t => t.MyId)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        ToTable("MyEntity", "MySchema");
    }
}

這將允許您分別為每個表設置架構,同時保持單個上下文。

既然您聲明要在不同的模式中使用相同的模型,那么在不了解您的設置的情況下會更加困難。 如果您只與少數客戶打交道並且不介意在代碼中維護他們的模式,那么您可以簡單地為每個模式創建一個映射(如上所述),然后為每個客戶添加一個新的DbSet。 如果你試圖讓這個可擴展到大量客戶,那么我強烈建議尋找一種不同的方法,因為當他在不同的模式中看到100多個相同的表而不是在每個表上使用customerID列時,你的dba可能會尖叫。

看看這些帖子

http://thedatafarm.com/data-access/digging-in-to-multi-tenant-migrations-with-ef6-alpha/

http://romiller.com/2011/05/23/ef-4-1-multi-tenant-with-code-first/

我想出了這個背景

public class DataLayerBuilder : DbContext
{
    private static  string conStr = string.Empty ;
    private DataLayerBuilder(DbConnection connection, DbCompiledModel model)
    : base(connection, model, contextOwnsConnection: false){ }
    public DbSet<Person> People { get; set; }

    private static ConcurrentDictionary<Tuple<string, string>, DbCompiledModel> modelCache
        = new ConcurrentDictionary<Tuple<string, string>, DbCompiledModel>();

    /// <summary>
    /// Creates a context that will access the specified tenant
    /// </summary>
    public static DataLayerBuilder Create(string tenantSchema)
    {
        conStr = ConfigurationManager.ConnectionStrings["ConnSTRName"].ConnectionString;
        var connection = new SqlConnection(conStr);
        var compiledModel = modelCache.GetOrAdd(
            Tuple.Create(conStr, tenantSchema),
            t =>
            {

                var builder = new DbModelBuilder();
                builder.HasDefaultSchema(tenantSchema);
                builder.Entity<Person>().ToTable("People");                   
                builder.Entity<Contact>().ToTable("Contacts");
                var model = builder.Build(connection);
                return model.Compile();
            });

        return new DataLayerBuilder(connection, compiledModel);
    }

    /// <summary>
    /// Creates the database and/or tables for a new tenant
    /// </summary>
    public static void ProvisionTenant(string tenantSchema)
    {
        try
        {
            using (var ctx = Create(tenantSchema))
            {
                if (!ctx.Database.Exists())
                {
                    ctx.Database.Create();
                }
                else
                {
                    ctx.Database.Initialize(true);

                }
            }
        }
        catch (Exception)
        {

            throw;
        }
    }
}

到目前為止,我已經能夠使用以下代碼添加多個租戶

 public void ProvisionTest()
    {
        //Arrange
        var tenant = "test2";

        //Act
        DataLayerBuilder.ProvisionTenant(tenant);

    }
}

改進上面的代碼我認為你可以編寫一個簡單的函數來更新每個用戶的表結構

我希望這有幫助

該解決方案可能最好看作是Robert Petz和alfkonne的結合,還有一些關於連接管理和遷移管理的工具。 對於客戶特定的備份目的,我更喜歡DB級別而非每個客戶的架構 您可以正確執行特定於架構的備份/恢復IF設置。 但請確保所涉及的任何外部工具都處理基於模式的恢復。

您可以在單個上下文中使用多個方案。 在每個實體或類中,您必須添加以下數據注釋:

[Table("TableName", Shema = "ShemaName")]

public class Entity
{

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM