1

방금 ​​EF 4.1 코드 우선 작업을 시작했으며 기본적으로 참조 (탐색 속성)가 LINQ-to-Entity로 쿼리 한 POCO 엔터티가있는 메모리로로드되지 않는다는 것을 알게되었습니다. DbEntityEntry.Reference을 사용하여 참조 된 항목을로드하는 데 성공하지 못했습니다. DbReferenceEntry.Load를 호출하면 다음 예외가 throw됩니다.EF 4.1 코드 우선 : 엔티티 참조를 메모리로로드하는 방법?

"이미이 명령과 연결된 열려있는 DataReader가 먼저 닫혀 야합니다." DataReader를 닫기

정말 내가 몇 가지 LINQ 쿼리의 중간에있을 때해야 할 일이 아니다. 여기

using (db1 = new NorthindDbContext(new SqlConnection(this.NORTHWIND))) { 
orders = db1.Orders.Where(o => !(o.CustomerId == null || o.ShipperId == null || o.EmployeeID == null)); 
      foreach (var o in orders) { 
       Shipper s = o.Shipper;//exception: "There is already an open DataReader associated with this Command which must be closed first." 
       DbEntityEntry<Order> entry = db1.Entry(o); 
       DbReferenceEntry<Order, Shipper> shipper_reference = entry.Reference<Shipper>("Shipper"); 
       if (!shipper_reference.IsLoaded) { 
        shipper_reference.Load();     
       } 
      } 
     } 

는 주문 클래스입니다 :

예를 들어, 다음은 작동하지 않습니다

public partial class Order 
{ 
    public System.Int32 ID { get; set; }     
    public System.Nullable<System.DateTime> OrderDate { get; set; } 
    public System.Nullable<System.DateTime> RequiredDate { get; set; } 
    public System.Nullable<System.DateTime> ShippedDate { get; set; }  
    public System.Nullable<System.Decimal> Freight { get; set; }   
    public Employee Employee { get; set; } 
    public Int32 CustomerId { get; set; } 
    public Customer Customer { get; set; } 
    public Int32 EmployeeID { get; set; } 
    /// <summary> 
    /// marked virtual for lazy loading 
    /// </summary> 
    public virtual Shipper Shipper { get; set; } 
    public Int32 ShipperId { get; set; } 
} 

내가 가상으로 Order.Shipper 속성을 표시하는 시도, 나는 여전히를 얻을 수 코드를 실행할 때도 같은 예외가 발생합니다.

[TestMethod]  
//configure MARS here? 
//Order.Shipper is not marked virtual now 
//... 
      using (db = new NorthindDbContext(new SqlConnection(this.NORTHWIND))) {       
      db.Orders.Include(o => o.Shipper) 
.Where(o => !(o.CustomerId == null || o.ShipperId == null || o.EmployeeID == null)); 
      foreach (var o in orders) { 
       Shipper s = o.Shipper;//null 
       DbEntityEntry<Order> entry = db.Entry(o); 
       DbReferenceEntry<Order, Shipper> shipper_reference = entry.Reference<Shipper>("Shipper"); 
       if (!shipper_reference.IsLoaded) { 
        shipper_reference.Load();//"There is already an open DataReader associated with this Command which must be closed first." 
       } 


      } 

는 EF 4.1 코드 첫째로, 당신은 어떻게 메모리에 참조 된 엔터티 부하를해야합니까 :

ObjectQuery.Include 방법, 작동합니까?

답변

3

여러 데이터베이스 읽기가 동시에 필요하면 allow MARS on your connection string을 사용해야하지만 실제 문제는 다른 곳에서 발생합니다.

EF는 기본적으로 탐색 속성을로드하지 않습니다. 게으른로드 또는 열망하는로드를 사용해야합니다. 게으른 로딩은 기업의 모든 탐색 속성을 가상 할 필요가 :

public class Order 
{ 
    ... 

    public virtual Shipper Shipper { get; set; } 
} 

일단 지연로드 및 프록시 생성이 컨텍스트에서 허용되는 처음 코드에 액세스 할 때 (기본값)은 재산이 자동으로로드됩니다. 이 액세스는 주문을로드하는 데 사용 된 것과 동일한 컨텍스트의 범위 내에서 발생해야합니다 (여는 DataReader로 오류를 계속 충족시킬 수 있음). 내가 가상으로 발송 속성을 표시 한

var query = context.Orders.Include(o => o.Shipper)... 
+0

,하지만 난 여전히 같은 예외를 얻을 :

다른 방법은 열망로드를 사용하여 Order와 직접 Shipper를로드하는 것입니다. 이를 반영하여 질문이 업데이트되었습니다. 나는 Inlcude 방법을 시도하고 그 방법이 효과가 있는지 살펴볼 것입니다. –

+0

클래스에'Customer' 속성도 있습니다 - 지연로드를 지원하려면 모든 탐색 속성이'virtual'이어야합니다. 또한 외부 쿼리 범위 내에서 지연로드를 사용하도록 MARS를 구성해야합니다. –

관련 문제