【问题标题】:EF Core with ASP MVC .NET 4.6带有 ASP MVC .NET 4.6 的 EF Core
【发布时间】:2018-01-29 19:49:47
【问题描述】:

在一个项目中,我需要设置一个 ASP.NET MVC(使用 .NET 4.6.1),但使用“新”EF Core 来访问数据库。

不幸的是,每个文档都只解释了如何设置 ASP.NET Core MVC 项目。

我刚刚试了一下,当通过包管理器控制台创建数据库时,我收到错误消息:

在“DataContext”上找不到无参数构造函数。要么添加一个 无参数构造函数到“DataContext”或添加一个实现 与“DataContext”在同一程序集中的“IDbContextFactory”

是的,我没有无参数构造函数,但微软的示例代码也没有

public DataContext(DbContextOptions<DataContext> options) : base(options) { }

我想问题是,我没有在 Startup.cs 中注册 DataContext,而我在“旧”ASP.NET MVC 应用程序中没有。

谁能帮我解决这个问题?

【问题讨论】:

  • 你如何在你的应用中提供连接字符串到上下文?
  • 您解决了这个问题吗?

标签: asp.net-mvc-5 entity-framework-core


【解决方案1】:

一个简单的例子

  • Example.EF(带有 EF Core 和 Microsoft 依赖注入的 .NET Standard 项目)。
  • Example.Tools - 参考 Example.EF(.NET Core CommandLine 项目仅为开发人员运行迁移)。
  • Example.MVC - 参考 Example.EF (MVC5)。

Example.EF 中:安装 EF Core、Microsft 依赖注入。创建一个类来支持 DI

public static class IocConfiguration
{
    public static void Configure()
    {
        var services = new ServiceCollection();

        services.AddDbContextPool<ExampleContext>(options => {
            options.UseSqlServer("_connectionstring_");
        });

        // Register to support the ExampleController can get DbContext.
        services.AddTransient(typeof(ExampleController));

        var serviceProvider = services.BuildServiceProvider();
        DependencyResolver.SetResolver(new DefaultServiceResolver(serviceProvider));
    }
}

public class DefaultServiceResolver : IDependencyResolver
{
    private readonly IServiceProvider _serviceProvider;

    public DefaultServiceResolver(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public object GetService(Type serviceType)
    {
        return _serviceProvider.GetService(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return _serviceProvider.GetServices(serviceType);
    }
}

Example.MVC 中,使用 Global.asax 中的 Application_Start 或 Startup with Owin

// Register services.
IocConfiguration.Configure();

// Example controller
public class ExampleController : Controller 
{
     private readonly ExampleContext _exampleContext;

     public ExampleController(ExampleContext exampleContext)
     {
         _exampleContext = exampleContext;
     }
}

运行迁移:

Add-Migration {MigrationName} -Project Example.EF -StartupProject Example.Tools

我们应该有 IDesignTimeDbContextFactory 来支持运行迁移。

【讨论】:

  • 有没有办法一次性注册所有的控制器?
  • @LucianBumb 在 IocConfiguration.Configure() 中,我们可以使用反射编写简单的代码来加载程序集中的所有控制器以进行注册。或者从您当前的 DI 库中已经支持它。 LightInject https://www.lightinject.net/mvc/ 的示例只需要调用 container.RegisterControllers(typeof(MyMvcApplication).Assembly);
【解决方案2】:

按照https://docs.microsoft.com/en-gb/ef/core/miscellaneous/cli/dbcontext-creation,你需要创建一个工厂。

来自设计时工厂

您还可以通过实现IDesignTimeDbContextFactory&lt;TContext&gt; 接口来告诉工具如何创​​建 DbContext:如果在与派生的DbContext 相同的项目中或在应用程序的启动项目中找到实现此接口的类,则工具绕过创建 DbContext 的其他方法并改用设计时工厂。 C#

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;

namespace MyProject
{
    public class BloggingContextFactory : IDesignTimeDbContextFactory<BloggingContext>
    {
        public BloggingContext CreateDbContext(string[] args)
        {
            var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
            optionsBuilder.UseSqlite("Data Source=blog.db");

            return new BloggingContext(optionsBuilder.Options);
        }
    }
}

注意 args 参数当前未使用。 an issue 跟踪从工具中指定设计时参数的能力。

如果您需要在设计时与运行时不同地配置 DbContext,如果 DbContext 构造函数采用未在 DI 中注册的附加参数,如果您不使用 DI,则设计时工厂可能特别有用全部,或者如果出于某种原因您不想在 ASP.NET Core 应用程序中使用 BuildWebHost 方法 Main类。

您不能在此处注入连接字符串,但这不是问题,因为这仅用于设计时功能,例如创建迁移。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-10
    • 2019-07-10
    相关资源
    最近更新 更多