2017-03-09 69 views
0

我有一些会计应用程序,它允许创建文档并为其添加一些位置(行/行)。 这里的控制器来获得特定文档的那些行:结合不同的查询

public JsonResult GetIncDocDetails(long id, int pagesize, int pagenum) 
    { 
     var dbResult = db.fooIncDocDetail.Where(d => d.DocumentID == id).Where(d => d.RecordStatusID != 2).Include(f => f.fooFood). 
          OrderBy(d => d.Date). 
          Select(s => new 
          { 
           s.IncDocDetailID, 
           s.FoodID, 
           s.MeasureUnit, 
           s.Amount, 
           s.Price, 
           s.VATRate,   
           s.Excise, 
           s.DocumentID, 
           s.UserID, 
           s.RecordDate,    
           s.RecordStatusID, 
           s.Date, 
           s.FoodName, 
           s.DetailNumber, 
           fooFoodName = s.fooFood.Name 
          }).Skip(pagesize * pagenum).Take(pagesize); 

     return Json(dbResult, JsonRequestBehavior.AllowGet); 
    } 

所以,我想通过这个控制器,如一些更多的信息:

  1. 这个特殊的文件中的所有行的总和:

    Summa = db.fooIncDocDetail.Where(d => d.DocumentID == id). 
            Where(d => d.RecordStatusID == 1). 
            Sum(a => (decimal?)(a.Amount* a.Price)) ?? 0; 
    
  2. 这个特殊的文件中的所有行的总计数:

    这个特殊的文件
    Total = db.fooIncDocDetail.Where(d => d.DocumentID == id). 
            Where(d => d.RecordStatusID != 2) 
            .Count() 
    
  3. 属性:

    Document = db.fooDocument.Where(d => d.DocumentID == id). 
                 Select(d => new 
                 { 
                  d.DocumentID, 
                  d.DocDate, 
                  d.RegNumber, 
                  d.UserID, 
                  d.RecordDate, 
                  d.RecordStatusID, 
                  d.RegistrationDate, 
                  d.Number, 
                  d.Description, 
                  d.ObjectID, 
                  d.DocumentTypeID, 
                  d.ContragentName, 
                  DocumentTypeName = d.fooDocumentType.Name 
                 }) 
    

但我怎么能结合所有,在短短一个LINQ查询,这是我写的第一?谢谢

+0

我不会尝试将所有这些查询合并成一个,而不是我想创建一个数据库中的参数化存储过程,并使用它。这可能会创造最少的开销,因为您只需发送一个查询并获得所有答案。 – Robert

+0

“fooDocument”和“fooInDocDetail”不相关吗?它们之间不应该有关系,所以你可以用'.Include()'加载所有相关的实体?既然你想要所有的细节,那么在数据库中执行聚合就不会使* all *有多大意义。一旦你在客户端上有数据,你就可以执行你想要的任何类型的聚合。 –

回答

1

基本上,您可以将所有的细节查询嵌入到最后一个查询Select中,方法是将它们投影到匿名或特定创建类型的属性中,以便原始(1)和(2)变为(3)的子查询。只要改变d变量来避免冲突,例如:

// The original query. Must be declared here and put into variable 
// to avoid exception due to `Skip`/`Take` subquery processing EF bug 
// It still will be executed as part of the other query 
var details = ...; 

var result = db.fooDocument 
    .Where(d => d.DocumentID == id). 
    .Select(doc => new 
    { 
     Document = new 
     { 
      doc.DocumentID, 
      doc.DocDate, 
      doc.RegNumber, 
      doc.UserID, 
      doc.RecordDate, 
      doc.RecordStatusID, 
      doc.RegistrationDate, 
      doc.Number, 
      doc.Description, 
      doc.ObjectID, 
      doc.DocumentTypeID, 
      doc.ContragentName, 
      DocumentTypeName = doc.fooDocumentType.Name 
     }, 
     Summa = ..., 
     Total = ..., 
     Details = details 
    }) 
    .FirstOrDefault(); 
+0

谢谢,伊万,请检查: –

+0

//请求详细信息= 详细信息= doc.fooIncDocDetail.Where(f => f.RecordStatusID!= 2)。 OrderBy(f => f.Date)。 选择(详细=>新的 { //一些明细属性 })。 跳过(pagesize * pagenum).Take(pagesize) 我得到了这个异常:Count必须是DbConstantExpression或DbParameterReferenceExpression –

+0

然后没有其他选择,而不是使'Details'部分分开。我有一些关于将它与其他部分相结合的抱怨,因为即使它起作用,它也会创建一个很大的联合查询,其中有许多字段在主数据库中未使用,许多字段在返回的单个结果集的详细记录中未使用。所以,排除来自答案的详细信息并执行2个查询,我认为它仍然优于4 :) –