【问题标题】:How to properly inject a DbContext for WebAPI using a ContextFactory and a repository?如何使用 ContextFactory 和存储库为 WebAPI 正确注入 DbContext?
【发布时间】:2016-02-05 00:20:11
【问题描述】:

我正在尝试为 Web API 背面的存储库的每个 Web 请求安全地注入数据​​库上下文。消费类调用存储库以检索对象,如果它返回 null,则它从不同的数据存储中获取对象并将其保存在数据库中以便以后更快地访问。这意味着它试图从数据库中获取,然后做一些事情,然后创建一条新记录。

目前我有这个存储库

public class OrganisationRepository : IOrganisationRepository
{
    public Func<IOrganisationDomainDbContext> ContextFactory { get; set; }

    public Organisation GetDetailByIdentifier(int id)
    {
        using (var context = ContextFactory.Invoke())
        {
            var org = context.Organisations.SingleOrDefault(x => x.Id == id);
            return org;
        }
    }

    public void Create(Organisation orgToCreate)
    {
        using (var context = ContextFactory.Invoke())
        {
            context.Organisations.Add(orgToCreate);
            context.SaveChanges();
        }
    }
}

并且存储库被注入到具有短暂生活方式的消费类中。每个 Web 请求都会注入 DbContext。

以前,Repository 被注入了单例生活方式,这在 Create 操作上中断了。

我的问题是,我是否通过使存储库瞬态来进行廉价的黑客攻击?这会给我带来麻烦吗?如果是这样,我应该怎么做?

编辑:有关更多信息,使用中的 DI 容器是 Castle Windsor 编辑:DI 安装程序的相关部分

public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(
                Component.For<IOrganisationDomainDbContext>().ImplementedBy<OrganisationDomainDbContext>().LifeStyle.PerWebRequest, 
                Component.For<Func<IOrganisationDomainDbContext>>().Instance(container.Resolve<IOrganisationDomainDbContext>), 
                Component.For<IOrganisationRepository>().ImplementedBy<OrganisationRepository>().LifeStyle.Transient, 
                Classes.FromThisAssembly().BasedOn<ApiController>().LifestylePerWebRequest());
        }

更新: 临时存储库没有解决问题,这是我的错误 - 我只是忘记了我正在查看的记录实际上已提交到数据库,因此未调用创建操作。我的错,道歉。

【问题讨论】:

  • 为什么在 Create 是 Singleton 时,存储库会中断?
  • 嗨,马克,这是一个 InvalidOperationException,因为 DbContext 已经被释放
  • ContextFactory.Invoke() 不是在每次调用时都创建一个新的DbContext 吗?
  • 这就是我的想法,但它似乎无法正常工作。它到达“context.Organisations.Add(orgToCreate)”并抛出异常。
  • 那个工厂是怎么实现的?

标签: c# entity-framework asp.net-web-api dependency-injection


【解决方案1】:

正如用户 jbl 指出的那样,我不需要在上下文使用周围使用 using 块 - DI 容器会在每个 Web 请求使用上下文时处理上下文。

下面是代码:

public class OrganisationRepository : IOrganisationRepository
{
    public Func<IOrganisationDomainDbContext> ContextFactory { get; set; }

    public Organisation GetDetailByIdentifier(int id)
    {
        var context = ContextFactory.Invoke()
        var org = context.Organisations.SingleOrDefault(x => x.Id == id);
        return org;
    }

    public void Create(Organisation orgToCreate)
    {
        var context = ContextFactory.Invoke();
        context.Organisations.Add(orgToCreate);
        context.SaveChanges();
    }
}

还有 DI 容器安装程序:

container.Register(
            Component.For<IOrganisationDomainDbContext>().ImplementedBy<OrganisationDomainDbContext>().LifeStyle.PerWebRequest, 
            Component.For<Func<IOrganisationDomainDbContext>>().Instance(container.Resolve<IOrganisationDomainDbContext>), 
            Component.For<IOrganisationRepository>().ImplementedBy<OrganisationRepository>().LifeStyle.PerWebRequest, 
            Classes.FromThisAssembly().BasedOn<ApiController>().LifestylePerWebRequest());

希望这是正确的答案,调试表明上下文在每个 Web 请求之后都被处理掉了,我没有遇到异常。感谢 jbl 和 Mark Seeman 的所有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-17
    • 1970-01-01
    • 2019-08-01
    • 2022-11-07
    • 2021-05-09
    • 1970-01-01
    • 2023-03-24
    相关资源
    最近更新 更多