2017-07-04 43 views
2

我有这个类:c。与虚拟财产查询#实体框架

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; } 
    } 

我想因为这个消息是虚拟的,所有的延迟加载的东西来获得联系的表,

这呼叫没有工作对我得到这个错误:

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection. in Reference Table

语法:

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 
       } 
      } 
} 

此外,有人可以给我解释一下这是如何工作的,以及如何与实体框架查询正确

工作

感谢

+0

请提供一些代码,以显示您如何使用上下文。如果连接关闭,延迟加载将不起作用。 – Harsh

+0

编辑帖子@Harsh – Zakk

回答

3

首先,你应该明白,这个代码不查询数据库:

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 

如何解决这个问题?请确保在处理查询和进行其他“懒惰”调用时数据库上下文不会丢失。或者在第二个例子中使用急切加载。预先加载可以让你当你执行查询的负载相关实体:

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

在这种情况下,不需要额外的“懒惰”的呼叫,这样你就可以配置数据库环境,并与查询结果的工作。

+0

如此急切的加载立即获得结果,而不是等到执行? – Zakk

+0

@Zakk急切的加载将会得到相关的实体,而不需要等到你需要它们。如果你不会执行它,查询本身可以延期。用'ToList()'调用(参见第一个例子) –

1

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

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