【问题标题】:Dependency Injection into Entity Framework seed method?依赖注入到实体框架种子方法?
【发布时间】:2016-11-29 12:19:19
【问题描述】:

是否可以将依赖项注入到Entity Framework 6的Configuration类中?

例如,像这样:

internal sealed class Configuration : DbMigrationsConfiguration<MyBaseContext>
{
    private readonly ILogger _logger;

    public Configuration(ILogger logger)
    {
        this._logger = logger;
        AutomaticMigrationsEnabled = true;
    }

    protected override void Seed(Home.DAL.Data.HomeBaseContext context)
    {
         //log something
    }
}

或者更一般的方法是获得在迁移内部注入代码的可能性:

public partial class InitialMigration : DbMigration
{        
    private readonly ILogger _logger;

    public InitialMigration(ILogger logger)
    {            
         this._logger = logger;
    }

    public override void Up()
    {
        CreateTable(...);
    }

    public override void Down()
    {
        DropTable(...);
    }
}

实体框架 6 中的 DI 初始化在哪里定义这些绑定?

更新

我不是在问我应该使用什么。目前,我正在使用 Ninject,但这是不可能的,因为无论我使用什么,我都应该能够将依赖项注入到迁移的构造函数中。当然,如果你写了我在上面的例子中写的东西,它只会给你抛出关于“没有默认构造函数”的异常。

上面示例中的 ILogger 只是一个简单的依赖示例。如果您有 IGeneratorService 会生成一些数据,并且您想使用此服务为 Seed 方法生成数据,情况会变得更糟。

【问题讨论】:

  • DI 初始化应该由您的 DI 框架处理。
  • 这个问题的任何部分的答案如何?
  • 您是否尝试过使用任何 DI 框架?
  • 实体框架不使用任何 DI 容器。这两种类型(DbMigrationsConfiguration、DbMigration)都是使用反射创建的,因此您不能使用构造函数注入或类似方法来执行此操作。
  • 如何运行这些迁移?使用Update-Database?

标签: c# entity-framework


【解决方案1】:

Entity Framework 6 建议您使用 .NET Framework 4.6 或更低版本,并且 .NET 4.6 或更低版本没有内置依赖注入功能,因此您必须使用第三方 DI 容器,例如 StructureMap、Ninject 等. 这些 DI 容器为您提供了 3 种获取依赖项注入的方法:通过构造函数、setter 或接口。

我不完全确定是否可以使用构造函数注入将依赖项注入ConfigurationInitialMigration 类,但我对此表示怀疑。即使有可能,您也无法按照您在问题中描述的方式注入ILoggerthis._logger = logger,因为 ILogger 是使用 ILoggerFactory Create() 方法初始化的。

因此,我认为一般情况下不可能使用构造函数注入将依赖项注入到您的 ConfigurationInitialMigration 类中。

如果你想在你的类中使用ILogger,下面的代码 sn-ps 应该可以工作:

internal sealed class Configuration : DbMigrationsConfiguration<MyBaseContext>
{
    private readonly ILogger _logger;

    public Configuration(ILoggerFactory loggerFactory)
    {
        this._logger = loggerFactory.Create("ConfigurationLogger");
        AutomaticMigrationsEnabled = true;
    }

    protected override void Seed(Home.DAL.Data.HomeBaseContext context)
    {
         //log something
         _logger.WriteInformation("Seeding data.");
    }
}

public partial class InitialMigration : DbMigration
{        
    private readonly ILogger _logger;

    public InitialMigration(ILoggerFactory loggerFactory)
    {            
         this._logger = loggerFactory.Create("InitialMigrationLogger");
    }

    public override void Up()
    {
        _logger.WriteInformation("Create table.");
        CreateTable(...);
    }

    public override void Down()
    {
        _logger.WriteInformation("Drop table.");
        DropTable(...);
    }
}

【讨论】:

    【解决方案2】:

    我不这么认为。尝试从命令行使用 update-database 时当然不会。请记住,您的 DI 容器是在运行时注册的。不会有任何注册的服务可以在任何地方注入。除此之外,EF 正在寻找具有无参数构造函数的配置文件。您可以使用问题中的示例自行快速测试。您将收到“在程序集 'Your.Assembly 中找不到迁移配置类型”。

    如果您特别希望在种子方法中从服务执行某些操作,那么我建议您查看已回答 here 的运行时 api。

    我在我的项目中使用了一个控制台应用程序,我可以在部署时将命令发送到我的构建管道中。您可以在实际代码库中轻松使用这种方法。

    private void RunMigrations()
        {
            Console.WriteLine("Starting migrations...");
            var configuration = new Configuration
            {
                TargetDatabase = new DbConnectionInfo(_connectionString, "System.Data.SqlClient")
            };
            var dbMigrator = new DbMigrator(configuration);
            dbMigrator.Update();
            Console.WriteLine("Migrations completed");
    
            //add your service here and do whatever you want.
        }
    
        private void Seed()
        {
            using (var MyContext = new MyContext(_connectionString))
            {
                Console.WriteLine("Seeding test data into database");
                //this is a custom seed method
                Initialize.Seed(_connectionString);
                Console.WriteLine("Seeding test data is complete");
    
                //add your service here and do whatever you want.
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-08
      • 1970-01-01
      • 2014-09-06
      • 2018-12-07
      • 1970-01-01
      相关资源
      最近更新 更多