2013-08-27 172 views
0

我試着去計算基於子查詢EF子查詢沒有導航屬性

var dtfs = cntx.Set<Models.DocTypeField>() 
       .Include(dtf => dtf.Field) 
       .Where(dtf => dtf.DocTypeId == docTypeId) 
       .Select(dtf => new 
      { 
       DocTypeField = dtf, 
       HasData = (cntx.Set<Models.DocumentData>() 
           .Any(dd => dd.DocTypeId == dtf.DocTypeId 
           && dd.DataValues.Any(ddv => ddv.FieldId == dtf.FieldId))) 
      }); 

DocTypeFieldDocumentData之間沒有導航屬性(或通過路徑)的布爾字段。當我運行上面的查詢,我得到以下異常:

試驗方法

Core.Sebring.DataAccess.Ef.Test.EF_DocTypeDALTest.EF_DocTypeDALTest_GetDocTypeIndexes 
threw exception: 
System.NotSupportedException: 
    LINQ to Entities does not recognize the method 
    'System.Data.Entity.DbSet`1[Core.Sebring.Models.DocumentData] 
    Set[DocumentData]()' method, and this method cannot be translated 
    into a store expression. 

有一個LINQ到實現上述查詢的實體呢?如果可能,我寧願不在DocTypeFieldDocumentData之間添加導航屬性(或可遍歷路徑)。

* 更新1 * 作爲一個工作圍繞我做

class FieldDocTypeField 
    { 
     public int DocTypeFieldId { get; set; } 
     public int DocTypeId { get; set; } 
     public int FieldDataType { get; set; } 
     public int FieldId { get; set; } 
     public byte[] LastChanged { get; set; } 
     public bool Required { get; set; } 
     public string FieldName { get; set; } 
     public bool HasData { get; set; } 
    } 

var dtfs = cntx.DbContext.Database.SqlQuery<FieldDocTypeField>(@"select dtf.*,f.*, 
      HasData = (CASE WHEN EXISTS(Select DocumentDataValue.FieldId 
      from DocumentData 
      inner join DocumentDataValue on DocumentData.DocumentDataId=DocumentDataValue.DocumentDataId 
      where DocumentData.DocTypeId = @DocTypeId AND dtf.FieldId = 1) THEN cast(1 as bit) ELSE cast(0 as bit) END) 
      from DocTypeField dtf 
      inner join Field f on dtf.FieldId = f.FieldId WHERE [email protected]", new System.Data.SqlClient.SqlParameter("@DocTypeId", docTypeId)); 

      foreach (var dtf in dtfs) 
      { 
       docTypeFields.Add(new Models.DocTypeField 
       { 
        DocTypeFieldId = dtf.DocTypeFieldId, 
        DocTypeId = dtf.DocTypeId, 
        FieldDataType = dtf.FieldDataType, 
        FieldId = dtf.FieldId, 
        LastChanged = dtf.LastChanged, 
        Required = dtf.Required, 
        FieldName = dtf.FieldName, 
        HasData = dtf.HasData 
       }); 
      } 

它不是那麼好,但它的工作原理,並完成同樣的事情。我無法找到一種方法來使用linq來實現上面的實體,而無需在DocTypeFieldDocumentData實體之間添加nav屬性。

+0

我可以向您保證,當您完成項目並在幾個月後返回時,您將無法理解此查詢。項目中的其他開發人員也一樣。 –

+0

另外,什麼類型是cntx變量? –

回答

0

您可以先拉內存中的數據,然後做第二select

var dtfs = cntx.Set<Models.DocTypeField>() 
    .Include(dtf => dtf.Field) 
    .Where(dtf => dtf.DocTypeId == docTypeId) 
    .ToList() // pull the data to memory and then the following select can execute successfully. 
    .Select(dtf => new 
    { 
     DocTypeField = dtf, 
     HasData = (cntx.Set<Models.DocumentData>() 
      .Any(dd => dd.DocTypeId == dtf.DocTypeId 
         && dd.DataValues.Any(ddv => ddv.FieldId == dtf.FieldId))) 
    }); 
+0

謝謝。我也不想要2個查詢。 – andrewramka

+0

@ user1916697這是一個查詢,第二個查詢從內存中查詢不是db,與您在列表中執行正常的linq相同。 – zsong