我在我的控制器中工作,但我想遵循最佳实践并将我的数据库逻辑放在模型中。
我想将所有数据库逻辑(选择,更新,删除,插入)放到MODEL中,因此我在模型中创建方法。
我检索数据的方法:
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;
}
}
这是我的模型视图:
public class ChatLogsNameViewModel
{
public UserProfile UserProfile { get; set; }
public string Message { get; set; }
public DateTime Time { get; set; }
}
我在我的控制器中调用我的getChatLogWithName()方法,如下所示:
List<ChatLogsNameViewModel> items = null;
using (var dba = new ChatLogContext())
{
items = dba.getChatLogWithName().ToList();
return View(items);
}
我得到的错误是:
由于已经处理了DbContext,因此无法完成操作。
这样做的正确方法是什么?我只想将集合(通过连接从2个表中的所有记录)传递给控制器。
答案 0 :(得分:2)
创建实例时,上下文的生命周期开始 当实例被处置或垃圾收集时结束。使用 如果您想要上下文控制的所有资源,请使用 布置在街区的尽头。使用时,编译器 自动创建一个try / finally块并调用dispose 最后阻止。
问题是当内部使用被释放时,它使DbContext无效。因此,您需要使用.ToList()
将查询结果保存在内存中。
假设在名为getChatLogWithName
的类中定义了Repo
,您可以将控制器逻辑更改为:
var repo = new Repo();
var items = repo.getChatLogWithName().ToList();
或将.ToList()
移至getChatLogWithName
。
顺便说一下,你不应该使用嵌套的DbContexts,在控制器中,你不必使用另一个DbContextscope包装它。
答案 1 :(得分:2)
确保在处理后不会引用DBContext。如何返回列表,这样您就不必致电.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();
}
}
和
items = dba.getChatLogWithName();
或者
由于dba
似乎与db
相同,因此您无法更改代码以使用dba
实例,该实例在using
结束前不会被释放控制器内的{1}}语句。
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;
}