Reputation: 7562
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.
Upvotes: 0
Views: 206
Reputation: 54514
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.
Upvotes: 2
Reputation: 6516
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;
}
Upvotes: 2