Asp.net mvc 4 获得';上下文是不可构造的。添加默认构造函数或提供IDbContextFactory的实现;

Asp.net mvc 4 获得';上下文是不可构造的。添加默认构造函数或提供IDbContextFactory的实现;,asp.net-mvc-4,ef-code-first,ninject,entity-framework-5,entity-framework-migrations,Asp.net Mvc 4,Ef Code First,Ninject,Entity Framework 5,Entity Framework Migrations,当我尝试使用代码优先迁移时,出现此错误 我的上下文有一个连接名为的构造函数 public class VeraContext : DbContext, IDbContext { public VeraContext(string NameOrConnectionStringName = "VeraDB") : base(NameOrConnectionStringName) { } public IDbSet<User> Users

当我尝试使用代码优先迁移时,出现此错误

我的上下文有一个连接名为的构造函数

public class VeraContext : DbContext, IDbContext
{
    public VeraContext(string NameOrConnectionStringName = "VeraDB")
        : base(NameOrConnectionStringName)
    {
    }

    public IDbSet<User> Users { get; set; }
    public IDbSet<Product> Products { get; set; }
    public IDbSet<IntCat> IntCats { get; set; }
}
public类上下文:DbContext,IDbContext
{
公共上下文(字符串名称或连接字符串名称=“VeraDB”)
:base(名称或ConnectionStringName)
{
}
公共IDbSet用户{get;set;}
公共IDbSet产品{get;set;}
公共IDbSet IntCats{get;set;}
}
这个连接名在项目运行时被注入ninject,我也在上面的代码中将它指定为默认名称,但这没有帮助

kernel.Bind<IDbContext>()
    .To<VeraContext>()
    .WithConstructorArgument("NameOrConnectionStringName", "VeraDB");
kernel.Bind()
.至()
.带有构造函数参数(“名称或连接字符串名称”、“VeraDB”);
当我尝试使用“Enable migrations”添加迁移时,抛出了一个错误:

目标上下文“VeraData.EF.Infrastructure.VeraContext”不可用 可构造的。添加默认构造函数或提供实现 IDbContextFactory的

如果我从
VeraContext
中删除构造函数,它将工作,但会创建另一个名为
VeraData.EF.Infrastructure.VeraContext
的数据库


我假定
ninject
仅在项目运行时传递连接字符串,而不是在我使用代码首次迁移时传递。无论如何,在使用代码优先迁移时,我可以为连接名注入/提供默认值?

基本上,您需要一个默认的ctor(这就是错误所在)——但仅仅实现它就会导致问题


您必须实现
IDbContextFactory
,以使结果保持一致(否则从代码进行的迁移将不起作用等等)

迁移实际上调用默认构造函数来生成一个 连接。所以你是另一个
角色
没什么大不了的

这里是基本的工厂

public class MyContextFactory : IDbContextFactory<MyContext>
{
    public MyContext Create()
    {
        return new MyDBContext("YourConnectionName");
    }
}
公共类MyContextFactory:IDbContextFactory
{
公共MyContext创建()
{
返回新的MyDBContext(“YourConnectionName”);
}
}

您应该将其与注入相结合,以便按照您的意愿注入和构造DbContext

如果您不想花时间查看IDbContextFactory选项,也不想让事情正常进行,请创建一个默认构造函数,并在调用基本DbContext时硬编码连接字符串的名称:

public class CustomContext : DbContext
{
    public CustomContext() :base("name=Entities") {} 
}

SRC:

为了补充@nccsbim071的答案,我还要补充一点。。。此选项不喜欢具有默认参数的构造函数。。。例如:

public MyContext(bool paramABC = false) : base("name=Entities") {...}
相反,您必须创建一个非参数(默认)构造函数和参数构造函数,就像旧的方式一样

public MyContext() :base("name=Entities") {...} 
public MyContext(bool paramABC) : this() {...}
注:

  • 实体
    在本例中表示连接字符串名称。。。按照惯例,上下文的名称与连接字符串名称相同,并且由于
    MyContext
    实体
    不同,因此需要手动指定它

在我的情况下,我想使用默认连接工厂,而不是显式地提供一个。在EF6中的某个地方,它将尝试查找工厂,但失败并显示此异常消息。通过查看EF6代码,我发现了这一点。Ado正在包装连接工厂,这导致找不到匹配项。

当某个地方的人正在执行
内核时,所有的ninject操作都会发生。获取
。您需要添加一个默认的ctor,或者等待有人告诉您如何通过Ninject(我猜这就是您正在做的!)钩住迁移的东西来构造对象。您必须实现
IDbContextFactory
,才能使结果保持一致(或者从代码进行的迁移无法工作等等)。本质上,您需要一个默认的ctor(这就是错误)-但是仅仅实现它就会导致问题。
IDbContextFactory
对于注入来说是不好的,它根本无法工作-通过设计。我还看不出它的意义…你能进一步解释一下你的意思吗,你不能注入,因为
Create()
不带参数,而且必须有一个默认构造函数,它总是被调用的构造函数-因此,无处注入。至少,没有构造函数注入。13这是很久以前的事了,但我记得,这是为了确保一致的DbContext构造。通常,EF会自动调用默认的ctor,不管您是否需要,所以您需要一个,而自定义ctor不会被调用。Factory主要用于EF调用,通常可以在DbContext上使用注入。但是b)据我回忆,大多数IoC容器(我不太使用ninject)都有定义的方法,例如container.Create,然后使用一些匿名方法来参与工厂(如果工厂更复杂,那么您需要进行检查,否则就像我说的那样)@NSGaga-为什么我们不能通过构造函数将DbContext或连接字符串注入MyContextFactory,然后返回DbContext而不是在create方法中新建一个DbContext?dotnetter您可以做各种事情-但是,DbContext通常是短期的,一次性对象-并且(在99%的情况下)不应该保存、重复使用或更多地作为单例使用(这可能会导致问题)。另一方面,EF将核心信息保存在一个静态文件中,并在不同的实例上重用,因此整个创建、分解过程都是高效的。简言之,如果我正确理解了您的意图,就没有必要进行这样的优化。@NSGaga谢谢。这是有道理的。但是我尝试注入(IoC)连接字符串名称,而不是硬编码,但没有成功。使用Ninject(或任何IoC)的目的不就是让连接字符串名称可以独立于实际的DbContext进行配置吗?那么,为什么要这样硬编码连接字符串名称呢<代码>启用迁移
提供一个命令行选项,为命令提供连接字符串名称。我的问题是,我们如何注入连接字符串名称