Maxim Zaslavsky
Maxim Zaslavsky

Reputation: 18065

Getting around "DataContext accessed after Dispose" error in ASP.NET MVC View

I have an ASP.NET MVC 2 action that looks like this:

public ActionResult Index()
    {
        using(var db = new MyDataContext())
        {
            var welcomeSnippet = "test";
            var articles = db.Posts.Where(p => p.DateOfPublish <= DateTime.Now).Take(5).ToList();
            return View(new HomeViewModel()
            {
                Articles = articles,
                WelcomeSnippet = welcomeSnippet
            });
        }
    }

The view includes the following code:

<%foreach (var item in Model.Articles)
{%>
     <div class="article" id="<%=item.PostID %>">
          <!-- some properties -->
          <div class="tags">tags: <i><%foreach (var tag in item.PostTags.ToList())
                                        { %><%=Html.Encode(tag.Tag.TagName.Trim())%> <%} %></i>
          </div>
     </div>
<% } %>

I'm accessing item.PostTags, which is obtained through my DataContext. Here, I'm essentially using lazy-loading, but I'm getting an error: my DataContext is already disposed when it comes time to list those PostTags.

How can I load such data before my DataContext is disposed?

Upvotes: 2

Views: 5702

Answers (1)

RPM1984
RPM1984

Reputation: 73132

Two options:

1) Manually Dispose of DC (e.g Application_EndRequest in Global.asax)

2) Eager load item.Tags in Controller:

using(var db = new MyDataContext())
        {
            var welcomeSnippet = "test";
            var articles = db.Posts.Include("PostTags").Where(p => p.DateOfPublish <= DateTime.Now).Take(5).ToList();

            return View(new HomeViewModel()
            {
                Articles = articles,
                WelcomeSnippet = welcomeSnippet
            });
        }

I would go option 2, as option 1 is risky without the use of a DI container. (which your obviously not using).

EDIT

Sorry - i thought you were using Entity Framework, here is the L2SQL equivalent of "eager loading":

You need to use DataLoadOptions

using(var db = new MyDataContext())
        {
            var dataLoadOptions = new DataLoadOptions();
            dataLoadOptions.LoadWith<Post>(x => x.PostTags);
            db.LoadOptions = dataLoadOptions;

            var welcomeSnippet = "test";
            var articles = db.Posts.Where(p => p.DateOfPublish <= DateTime.Now).Take(5).ToList();

            return View(new HomeViewModel()
            {
                Articles = articles,
                WelcomeSnippet = welcomeSnippet
            });
        }

Upvotes: 6

Related Questions