繁体   English   中英

ASP.NET Boilerplate-“ ObjectContext实例已被处置”异常

[英]ASP.NET Boilerplate - “The ObjectContext instance has been disposed” exception

我正在尝试使用ASP.NET Boilerplate处理我的项目,但我遇到了一个严重的问题。

我有2个模特:照片和评论:

public class Comment : Entity<int>
{
    [DataType(DataType.MultilineText)]
    public string Text { get; set; }
    public string Author { get; set; }

    public int ItemID { get; set; }
    public virtual Item Item { get; set; }
}

public class Item : Entity<int>
{
    public string Title { get; set; }

    public string Description { get; set; }

    public ItemSourceType SourceType { get; set; }

    public byte[] PhotoBytes { get; set; }

    public string Url { get; set; }

    public virtual ICollection<Comment> Comments { get; set; }

}

另外,我已经基于RepositoryBase<Item>创建了默认的OOB存储库,并且对Comment

当我尝试获得像这样的商品时,存在问题:

    public ActionResult Details(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }

        Item item = _repoItems.Get(id.Value);
        if (item == null)
        {
            return HttpNotFound();
        }
        return View(item);
    }

当我调试此代码时,我可以在Comments属性中看到该item具有此异常。

我是否缺少ASP.NET Boilerplate的内容?

感谢您的帮助!

//编辑:完整的异常消息:

{"The ObjectContext instance has been disposed and can no longer be used for operations that require a connection."}

我只是偶然发现了同样的问题。 似乎是UnitOfWork实现为每个“ UnitOfWork”创建并布置了一个新的DbContext。

因此,要解决该特定问题,请尝试注入“ IUnitOfWorkManager”并调用

public ActionResult Details(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }

        using(var uow = _unitOfWorkManager.Begin())
        {
            try
            {
                Item item = _repoItems.Get(id.Value);
                if (item == null)
                {
                    return HttpNotFound();
                }
                return View(item);
            }
            finally
            {
               uow.Complete()
            };
        }
    }

如果可行,请考虑在ApiController的构造函数中调用“ Begin()”,并在其“ Dispose()”替代中调用“ Complete()”。 希望有帮助!

否。问题很可能在您的存储库中,不幸的是您未包含其中的代码。 如果我不得不猜测,我会说您在该存储库方法中使用的是以下内容:

using (var context = new ApplicationContext())
{
    // fetch something
}

您的Comments属性是虚拟的,这意味着默认情况下,Entity Framework将延迟加载它,仅当您尝试访问该属性时才向数据库实际发出该查询。 但是,到那时,您的上下文已被处置,因为存储库方法已完成其工作,并且您的上下文仅在using块内可用。

有很多方法可以解决此问题。 您可以热切地在using块中加载注释:

return context.Items.Include("Comments").Find(id);

但是,这确实可以解决问题。 您可以做的最好的事情就是不使用using 理想情况下,对于每个请求,您的上下文应实例化一次,并且只能实例化一次。 最简单的方法是使用依赖项注入容器,并向您的存储库中添加一个接受上下文的构造函数:

public class MyAwesomeRepository
{
    private readonly ApplicationContext context;

    public MyAwesomeRepository(ApplicationContext context)
    {
        this.context = context;
    }
}

DI容器的配置将根据您选择的配置而有所不同,但是通常,您需要确保将上下文类绑定到请求范围。

我在ASP.NET Boilerplate中遇到了类似的问题,并发现只有当您根据接口和类的命名约定命名该接口和类时,此框架才能正确实现所有DI魔术。 您可以通过某种方式手动进行操作,但是您必须深入了解ABP架构,而不是想要的。

@ChrisPratt发布的链接(请参阅答案中的评论)说:

命名约定在这里非常重要。 例如,您可以将PersonAppService的名称更改为MyPersonAppService或其他包含“ PersonAppService”后缀的名称,因为IPersonAppService具有此后缀。 但是您不能将服务命名为PeopleService。 如果执行此操作,则不会自动为IPersonAppService注册(它已注册到DI框架,但已通过自注册,而不是通过接口注册),因此,如果需要,应手动注册。

就我而言,我有一个名为ProductService的服务,该服务实现了IProductAppService接口。 在我将服务重命名为ProductAppService之前,它因ObjectDisposedException异常而失败。

我认为OP仍然没有这个问题,但是希望它将为像我一样在ABP方面苦苦挣扎的人们节省几个小时。 :-)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM