あなたのすべての制限を解決する解決策が見えません。これは、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.
});