使用 DbMigrationsConfiguration 自定义 DbContextFactory

问题描述 投票:0回答:2

您将在下面找到我的自定义 IDbContextFactory 实现。在我的存储库中,我创建了这个工厂的一个实例,因为我正在做一个多租户应用程序(每个租户都有自己的数据库),所以我还需要设置 ConnectionString 和 Tenant 属性,以便可以创建我的 DbContext。

如果数据库不存在,这一切都非常有用,但是当我需要执行迁移时,DbMigrationsConfiguration 尝试使用此工厂来创建 EFDbContext 的实例,当然它会失败,因为未设置 ConnectionString 和租户。

有人有解决此问题的替代策略吗?

public class DbContextFactory : IDbContextFactory<EFDbContext>
{
    public string ConnectionString { get; set; }
    public string Tenant { get; set; }

    public EFDbContext Create()
    {
        var connectionInfo = new DbConnectionInfo(ConnectionString, "System.Data.SqlClient");

        if (EFContextHelper.Contexts.Contains(Tenant))
        {
            return new EFDbContext(ConnectionString, Tenant);
        }
        else
        {
            EFDbContext context = new EFDbContext(ConnectionString, Tenant);

            if (!context.Database.Exists())
            {
                Database.SetInitializer<EFDbContext>(new EFDbContextInitializer());
                context.Database.Initialize(false);
            }
            else
            {
                bool doMigration = false;
                try
                {
                    doMigration = !context.Database.CompatibleWithModel(true);
                }
                catch (NotSupportedException)
                {
                    // no metadata for migration
                    doMigration = true;
                }

                // not working cause migrator is trying to instantiate this factory without setting connection string etc
                if (doMigration)
                {
                    var migrationConfig = new DbMigrationsConfiguration<EFDbContext>(); 
                    migrationConfig.AutomaticMigrationDataLossAllowed = false;
                    migrationConfig.AutomaticMigrationsEnabled = true;
                    migrationConfig.TargetDatabase = connectionInfo;
                    var migrator = new DbMigrator(migrationConfig);
                    migrator.Update();
                }
            }

            EFContextHelper.Contexts.Add(Tenant);

            return context as EFDbContext;
        }
    }

谢谢, 加里

entity-framework-5 dbcontext entity-framework-migrations
2个回答
2
投票

我自己设法解决了这个问题。由于我没有收到任何回复,因此我将其留给遇到此问题的其他人。

基本上我只是将 DbContext 类实例化调整为以下内容:

public EFDbContext(string connectionString, string tenant) : base(connectionString ?? "EFDBContext")
{
     Tenant = tenant;
}

因此,在这种情况下,如果传递的连接字符串为空,则它只是默认为配置文件连接字符串名称。迁移器似乎保留分配的连接:

migrationConfig.TargetDatabase = connectionInfo;

希望这对某人有帮助。


0
投票

我也有类似的问题,我在构造函数中设置了TenantId值,但是迁移不起作用,无法创建实例

    public TenantDbContext(DbContextOptions<TenantDbContext> options, IMemoryCache memoryCache, IHttpContextData contextData, ICryptography cryptography, IConfiguration configuration, IDbUtilities dbUtilities, ISharedLocalizer sharedLocalizer, SeedStatikReferanslar seedStatikReferanslar, SeedRefTip seedSystemReferanslar, SeedReferanslar seedReferanslar, bool DoNotSeedDB = false) : base(options) { _memoryCache = memoryCache; _contextData = contextData; _seedStatikReferanslar = seedStatikReferanslar; _configuration = configuration; _dbUtilities = dbUtilities; _seedSystemReferanslar = seedSystemReferanslar; _seedReferanslar = seedReferanslar; DoNotSeed = DoNotSeedDB; _cryptography = cryptography; _sharedLocalizer = sharedLocalizer; CurrentSingleDbMode = contextData.SingleDbMode; CurrentTenantId = contextData.TenantId; }
我需要单个数据库租户和全局查询的这两个当前值,应用程序正常工作,但迁移却没有,有人有任何解决方案吗?

© www.soinside.com 2019 - 2024. All rights reserved.