0

I have this working in my controller, but I want to follow best practices and put my database logic in Model.

I want to put all database logic (select, update, delete, insert) to MODEL, therefore I create methods in my model.

My method for retrieving the data:

public IQueryable<ChatLogsNameViewModel> getChatLogWithName()
{
    using (var db = new ChatLogContext())
    {
        var list = (from b in db.ChatLogs
                    select new ChatLogsNameViewModel()
                    {
                        UserProfile = b.UserProfile,
                        Message = b.Message,
                        Time = b.Time
                    });

        return list;
    }
}

This is my modelView:

public class ChatLogsNameViewModel
{
    public UserProfile UserProfile { get; set; }
    public string Message { get; set; }
    public DateTime Time { get; set; }

}

I call my getChatLogWithName() method in my controller like this:

List<ChatLogsNameViewModel> items = null;
using (var dba = new ChatLogContext())
{
    items = dba.getChatLogWithName().ToList();
    return View(items);
}

Error I get is:

The operation cannot be completed because the DbContext has been disposed.

What is the proper way to do this? I just want to pass collection (all records from 2 tables via join) to controller.

4
  • Controller is disposable. Make context a field and dispose it when controller is disposed. Commented Aug 7, 2013 at 18:09
  • I am beginner can you elaborate more please? Thank you. Commented Aug 7, 2013 at 18:14
  • @abatishchev 3ass in title... Commented Aug 7, 2013 at 18:37
  • @sza: Sorry, a typo. Thanks, fixed! Commented Aug 7, 2013 at 18:47

2 Answers 2

2

To ensure that the DBContext is not getting referenced after disposal. How about returning a list so you dont have to call .ToList():

public List<ChatLogsNameViewModel> getChatLogWithName()
    {
        using (var db = new ChatLogContext())
        {
            var list = (from b in db.ChatLogs
                        select new ChatLogsNameViewModel()
                        {
                            UserProfile = b.UserProfile,
                            Message = b.Message,
                            Time = b.Time
                        });

            return list.ToList();
        }
    }

and

items = dba.getChatLogWithName();

Or

Since it appears that dba is the same as db, couldn't you change your code to use the dba instance which won't get disposed until the end of your using statement within your controller.

public IQueryable<ChatLogsNameViewModel> getChatLogWithName()
    {

            var list = (from b in this.ChatLogs
                        select new ChatLogsNameViewModel()
                        {
                            UserProfile = b.UserProfile,
                            Message = b.Message,
                            Time = b.Time
                        });

            return list;
    }
Sign up to request clarification or add additional context in comments.

1 Comment

Yeah I made a mistakes with not knowing when does dispose fires in this case. I understand what do you mean. I could use "global" context but I thought you have to use "using" in controller for more safety.
2

Lifetime - DbContext

The lifetime of the context begins when the instance is created and ends when the instance is either disposed or garbage-collected. Use using if you want all the resources that the context controls to be disposed at the end of the block. When you use using, the compiler automatically creates a try/finally block and calls dispose in the finally block.

The problem was when the inner using got disposed, it invalidated the DbContext. So you need to use .ToList() to save the query result in memory.

Suppose getChatLogWithName is defined in the class called Repo, you can change the controller logic to something like this:

var repo = new Repo();
var items = repo.getChatLogWithName().ToList();

Or move .ToList() to getChatLogWithName.

Btw, you should not use the nested DbContexts cope, in your controller, you don't have to wrap it using another DbContextscope.

2 Comments

yes i agree, i thought that using "using" is more safe way always, so you don't need to use "using" in controllers? making private instance at top is just enough?
using is more safe. However it does not allow access to the IQueryable that is needed for WebAPI OData to work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.