4

次のようなものがあります。

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

linq でどのように記述しますか? それとも、単純に不可能ですか?

制限事項:

  • データベースにヒットできるのは 1 回だけです。

       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

4

1 に答える 1

5

あなたのすべての制限を解決する解決策が見えません。これは、ORM マッパーを使用する際の警告の 1 つであり、生成された 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.
                                       });
于 2013-07-11T11:58:44.150 に答える