C# 具有虚拟属性查询的c实体框架

C# 具有虚拟属性查询的c实体框架,c#,entity-framework,linq-to-entities,C#,Entity Framework,Linq To Entities,我有这门课: public class Message { public Message() { Contacts = new List<Contact>(); } public Message(string Sub_Message, string Body_Message, string Date_Send_Message) { Cont

我有这门课:

    public class Message
    {
        public Message()
        {
            Contacts = new List<Contact>();
        }

        public Message(string Sub_Message, string Body_Message, string Date_Send_Message)
        {
            Contacts = new List<Contact>();

            Subject = Sub_Message;
            Body = Body_Message;
            Date = Date_Send_Message;
        }

        public int MessageId { get; set; }
        public string Subject { get; set; }

        public string Date { get; set; }

        public string Body { get; set; }

        public virtual IList<Contact> Contacts { get; set; }
    }
我想得到联系人的表格,因为消息是虚拟的,所有的延迟加载的东西

此呼叫对我无效,出现以下错误:

ObjectContext实例已被释放,无法再使用 用于需要连接的操作。在参考表中

语法:

    public ObservableCollection<Model.Message> LoadMessages()
    {
      using (db) {
       var x = from qr in db.Messages
                            order by qr.Subject
                            select qr;
          }
     }
虽然这样做有效:

public ObservableCollection<Model.Message> LoadMessages()
{
    using (db)
    {
        var Messages = db.Messages.Include(z => z.Contacts).ToList();

        return new ObservableCollection<Model.Message>(Messages); 
    }
}
因此,我在一个名为MessageService的服务中使用查询,每次我想要使用dbContext时,我都会为它创建一个函数,并将其放入usingdb中

像这样:

     public class MessageService
        {
            ReadingFromData db = new ReadingFromData();
            public ObservableCollection<Model.Message> LoadMessages()
            {
                using (db)
                {
                    //Do something with db
                }
            }
}
另外,有人能给我解释一下这是如何工作的,以及如何使用实体框架查询吗


谢谢

首先,您应该了解此代码不会查询数据库:

var x = from qr in db.Messages
        orderby qr.Subject
        select qr;
它只是一个查询定义表达式,应该将其转换为SQL并在执行时发送到数据库服务器。执行是枚举查询结果,或使用具有立即执行类型的LINQ运算符之一,请参阅。也就是说,当稍后在代码中枚举x或尝试将查询结果存储在列表中时,可能已经释放了数据库上下文数据库。当然,你会得到一个错误

var x = db.Messages; // query is not executed
db.Dispose(); // context disposed
foreach(var m in x) // exception here, you try to execute query which uses disposed context
   ...
现在谈谈延迟加载。它的工作原理是将数据库上下文存储在从实体继承的代理实体中。因此,实际上db.Messages将返回某种类型的实体MessageWithDbContext,其中db值存储在内部。它是以后进行其他“惰性”数据库查询所必需的。同样,如果此时数据库上下文被释放,那么您将得到一个异常:

 var x = db.Messages.ToList(); // query is executed, messages are loaded
 db.Dispose();  // context disposed
 foreach(var m in x)
    m.Contacts.Count(); // exception - you try to execute contacts query with disposed db
如何解决这个问题?在处理查询和进行其他“惰性”调用时,请确保未释放数据库上下文。或者像在第二个示例中那样使用即时加载。即时加载允许您在执行查询时加载相关实体:

 // both messages and contacts are loaded from database when you execute the query
 var x = db.Message.Include(m => m.Contacts).ToList();
 db.Dispose();
 foreach(var m in x)
    m.Contacts.Count();

在这种情况下,不需要额外的“延迟”调用,因此您可以处理数据库上下文并处理查询结果。

只有在打开或未处理与上下文的连接时访问属性时,延迟加载才会起作用

            using (db)
            {
                //If you try to load the data here, lazy loading will work.
            }
现在,当您使用include时,EF会立即加载并为您获取相关数据。这就是为什么在使用include时数据可用的原因

var Messages = db.Messages.Include(z => z.Contacts).ToList(); 

请提供一些代码来说明如何使用上下文。如果连接关闭,延迟加载将不起作用。编辑后@HarshSo-eanger-loading立即获得结果,而不是等待执行?@Zakk-eanger-loading将获得相关实体,而不等待您需要它们。如果您不执行查询,则可以延迟查询本身,例如,使用ToList调用,请参阅第一个example@SergeyBerezovskiy一个问题是,为什么每个人都想在类中保存集合时使用公共虚拟ICollection,为什么它不只是公共列表myList?