2013-07-11 27 views
4

具有相似的東西:獨立的子查詢到LINQ聲明(打DB僅一次)

SELECT (SELECT COUNT(*) from Table1),(SELECT COUNT(*) from Table2) 

我怎樣寫它在LINQ?或者是簡單的不可能?

限制

  • 只能打到數據庫中的一個時間:

    var result = new { 
           Sum1 = db.Table1.Count(), 
           Sum2 = db.Table2.Count() 
           }); // is not valid..... 
    
  • 我不希望使用類似的東西(使用 「幫助」 表):

    var result = (from t3 in db.Table3 
          select new { 
           Sum1 = db.Table1.Count(), 
           Sum2 = db.Table2.Count() 
          }).firstOrDefault(); 
    //In order to get only the first row 
    //but it will not return nothing if the table 3 has no entries...... 
    
  • 不使用db.Database.ExecuteSqlCommand

+0

這是爲什麼第一條語句無效? – Magnus

+0

@Magnus我沒有使用任何SQL分析器,但我認爲這是生成兩個「獨立」查詢,而不是我正在尋找的SQL語句。 – Dryadwoods

+2

爲什麼這很重要? – Magnus

回答

5

我看不到解決方案,它解決了所有限制。這是使用ORM映射程序的注意事項之一,您無法控制生成的SQL。

在這種情況下,如果將多個查詢發送到數據庫是完全不可接受的,那麼嚴酷的事實是您必須自己編寫查詢。

更新

我得到了好奇,並創建了一個擴展方法可以做到這一點!當然,它構造了自己的SQL命令,它只適用於Linq2SQL。同時大規模免責聲明:這是相當骯髒的代碼,如果我有時間,我會在週末:)

public static TOut CountMany<TContext, TOut>(this TContext db, Expression<Func<TContext, TOut>> tableSelector) 
     where TContext: DataContext 
    { 
     var newExpression = (NewExpression) tableSelector.Body; 
     var tables = 
      newExpression.Arguments.OfType<MethodCallExpression>() 
         .SelectMany(mce => mce.Arguments.OfType<MemberExpression>()) 
         .ToList(); 
     var command = new string[tables.Count]; 
     for(var i = 0; i < tables.Count; i++) 
     { 
      var table = tables[i]; 
      var tableType = ((PropertyInfo) table.Member).PropertyType.GetGenericArguments()[0]; 
      var tableName = tableType.GetCustomAttribute<TableAttribute>().Name; 
      command[i] = string.Format("(SELECT COUNT(*) FROM {0}) AS T{1}", tableName, i); 
     } 

     var dbCommand = db.Connection.CreateCommand(); 
     dbCommand.CommandText = string.Format("SELECT {0}", String.Join(",", command)); 
     db.Connection.Open(); 
     IDataRecord result; 
     try 
     { 
      result = dbCommand.ExecuteReader().OfType<IDataRecord>().First(); 
     } 
     finally 
     { 
      db.Connection.Close(); 
     } 

     var results = new object[tables.Count]; 
     for (var i = 0; i < tables.Count; i++) 
      results[i] = result.GetInt32(i); 
     var ctor = typeof(TOut).GetConstructor(Enumerable.Repeat(typeof(int), tables.Count).ToArray()); 
     return (TOut) ctor.Invoke(results); 
    } 

的代碼被稱爲像這樣解決起來:

var counts = dbContext.CountMany(db => new 
             { 
              table1Count = db.Table1.Count(), 
              table2Count = db.Table2.Count() 
              //etc. 
             }); 
+0

我仍然沒有嘗試它,但乍一看,我會給你(至少)一個投票,只是爲了你的努力和動機找到答案:) – Dryadwoods

+0

謝謝x)我誤解了你的問題,並認爲你是使用Linq2Sql,而不是實體框架,所以我的代碼不會與你的無縫集成:/儘管只有tableName和dbCommand的提取應該不同! –