【问题标题】:Dependancy Injected DbContext is empty after populating DbContext created with new (EF7, ASP.NET 5, vnext)填充使用 new(EF7、ASP.NET 5、vnext)创建的 DbContext 后,依赖注入 DbContext 为空
【发布时间】:2015-01-29 07:45:26
【问题描述】:

我对 EF7 比较陌生,听说将 DbContext 依赖注入到 Controller 构造函数中是获取 DbContext 以在给定 Action 方法中使用的好方法。但是,在很多情况下无法进行依赖注入(例如,在普通类中访问 Db),必须使用using(VectorDbContext dbContext...) 模式。

我遇到了一个问题,即添加数据到使用using 模式创建的 DbContext 无法被依赖注入的上下文访问。 DbContext 是一个用于测试的简单 InMemory 数据库 - 它不连接任何东西。

这是将实体添加到 DbContext 的代码,用于测试我在 Startup.cs 中调用它:

using (ExampleDbContext dbContext= new ExampleDbContext()) {
    dbContext.Things.Add(
        new Thing() {
            Stuff= "something"
        });

    dbContext.SaveChanges();
}

这是控制器中的访问代码:

public class ExampleController : Controller {
    public ExampleController(ExampleDbContext exampleDbContext) {
        this.ExampleDbContext= exampleDbContext;
    }

    public ExampleDbContext ExampleDbContext { get; set; }

    public async Task<IActionResult> ExampleAction() {

        // new DbContext:
        using(ExampleDbContext dbContext = new ExampleDbContext ()) {
            var List1 = (await dbContext.Things
                .AsNoTracking()
                .ToListAsync());
        }

        // Injected DbContext:
        var List2 = (await this.ExampleDbContext.Things
            .AsNoTracking()
            .ToListAsync());
    }
}

单步执行时,List1 中包含预期的一项,但 List2 始终为空!

我做错了什么?看起来 DbContext 不知何故不同步,依赖注入如何创建 DbContext/它来自哪里?

编辑:我刚刚做了一些额外的测试,并确认在使用new 创建的 DbContext 中添加的任何实体仅在 new 中可见,并且在 Injected DbContext 中添加的实体仅在 Injected DbContext 中可见,让我相信他们正在连接到不同的支持数据库,但我无法确认。

【问题讨论】:

  • 关于 DbContext 注入发生的位置:我已经实现了 SimpleInjector 来为我执行此操作,遵循我们受人尊敬的 S.O.成员Steven 和他的blog 关于如何实现它。我发现他的方法非常有用,也许您可​​以通过他的演练解决您的问题!
  • @Ryan - 这不是同一个 DbContext。你创建了一个新的。它是两个独立的 DbContext,因此它们的内部缓存中当然包含不同的数据集。我不知道你为什么要创建一个新实例..
  • @Ryan - 另外,你 100% 错了(好吧,99.9% 错了)“在很多情况下依赖注入是不可能的”。您根本不了解依赖注入以及您应该如何正确使用它。
  • @ErikFunkenbusch 关于两个独立的DbContexts,我同意你的看法,但它们不应该超出其内部缓存并直接查询数据库,因此返回相同的数据吗?跨度>
  • @Ryan - 同样,您对如何使用依赖注入缺乏了解,并声称您不能这样做或那样做,而您真正的意思是“我不明白如何做这个或那个”。首先,我建议需要在 RouteConstraint 中访问 DbContext 是一个非常糟糕的设计,并且违反了单一职责原则。您还没有解释为什么需要这个,所以我无法提供更好的解决方案。我猜你要么尝试实现某种多租户,要么尝试实现某种基于角色的路由。但是,通常你会注入一个工厂

标签: asp.net entity-framework dbcontext asp.net-core entity-framework-core


【解决方案1】:

我可能错了,但我的假设是,当您在代码中创建 DbContext 的新实例时,您正在使用将底层连接字符串设置为某个默认值的无参数构造函数。但是,DI 注入的DbContext 可以使用另一个具有不同连接字符串的构造函数来解析。

这是一个明确指定构造函数参数的 Unity 配置示例:

<register type="DbContext, [assembly-name]" mapTo="DbContext, [assembly-name]">
<constructor>
    <param name="nameOrConnectionString" value="Test"/>
</constructor>
</register>

所以我会检查你的容器的配置。

【讨论】:

  • 这绝对有可能——我知道当DbContext OnConfiguring 中使用无参数扩展方法来建立连接时,肯定会发生这种情况。我以前通过手动提供连接字符串来解决它,即options.UseSqlServer(Configuration.Get("Data:DefaultConnection:ConnectionString")); 而不是options.UseSqlServer()。但是,UseInMemoryStore() 似乎没有参数化重载,因此我无法立即对此做任何事情……我将深入研究一些 vNext 源代码。
猜你喜欢
  • 2015-01-25
  • 1970-01-01
  • 2015-07-04
  • 1970-01-01
  • 1970-01-01
  • 2019-04-30
  • 2020-05-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多