从模型到控制器的数据

时间:2013-08-07 18:04:56

标签: c# asp.net-mvc entity-framework

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

我想将所有数据库逻辑(选择,更新,删除,插入)放到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个表中的所有记录)传递给控制器​​。

2 个答案:

答案 0 :(得分:2)

  

Lifetime - DbContext

     

创建实例时,上下文的生命周期开始   当实例被处置或垃圾收集时结束。使用   如果您想要上下文控制的所有资源,请使用   布置在街区的尽头。使用时,编译器   自动创建一个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;
    }