0

我在我的控制器中有这个工作,但我想遵循最佳实践并将我的数据库逻辑放在模型中。

我想将所有数据库逻辑(选择、更新、删除、插入)放到模型中,因此我在模型中创建方法。

我检索数据的方法:

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 个表的所有记录)传递给控制器​​。

4

2 回答 2

2

生命周期 - DbContext

上下文的生命周期从创建实例时开始,到实例被释放或垃圾回收时结束。如果您希望将上下文控制的所有资源都放置在块的末尾,请使用 using。当你使用 using 时,编译器会自动创建一个 try/finally 块并在 finally 块中调用 dispose。

问题是当内部使用被处理时,它使 DbContext 无效。所以需要使用.ToList()将查询结果保存在内存中。

假设getChatLogWithName在名为 的类中定义Repo,您可以将控制器逻辑更改为如下所示:

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

.ToList()移至getChatLogWithName.

顺便说一句,您不应该使用嵌套的 DbContexts 处理,在您的控制器中,您不必使用另一个 DbContextscope 来包装它。

于 2013-08-07T18:19:45.247 回答
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

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;
    }
于 2013-08-07T18:27:49.460 回答