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

时间:2017-07-04 10:48:14

标签: 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)
        {
            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我为它创建一个函数并将其放入使用(db)

像这样:

     public class MessageService
        {
            ReadingFromData db = new ReadingFromData();
            public ObservableCollection<Model.Message> LoadMessages()
            {
                using (db)
                {
                    //Do something with db
                }
            }
}

此外,有人可以向我解释这是如何工作的,以及如何使用实体框架查询更正

由于

2 个答案:

答案 0 :(得分:4)

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

var x = from qr in db.Messages
        orderby qr.Subject
        select qr;

它只是一个查询定义(表达式),它应该被翻译成SQL并在执行时发送到数据库服务器。执行是枚举查询结果,或使用具有立即执行类型的LINQ运算符之一(请参阅Classification of Standard Query Operators by Manner of Execution)。即如果您稍后在代码中枚举x,或者您尝试将查询结果存储在列表中,则可能已经处理了数据库上下文db。当然,你会收到一个错误

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

如何解决这个问题?确保在处理查询时不处理数据库上下文,并使其他“懒惰”处理。调用。或者像在第二个示例中那样使用急切加载。 Eager loading允许您在执行查询时加载相关实体:

 // 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();

在这种情况下,没有额外的“懒惰”&#39;调用是必需的,因此您可以处置数据库上下文并使用查询结果。

答案 1 :(得分:2)

只有在与上下文的连接打开(或未处理)时访问属性时,延迟加载才有效。

            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();