1

このコードは正常に動作しますが、1 つの LINQ 式で記述して、結果セットを実現してからループする代わりに、データベース サーバーが単一のパスを実行できるようにする方法がないかどうか疑問に思っていました。コードが生成されます。

  var logs = from AssetLog log in dc.AssetLogs
             where log.AssetId == assetId && log.Recorded >= start && log.Recorded <= finish
             select log;
  return new GetInteractionBoundsResult()
  {
    N = logs.Max(log => log.Latitude),
    S = logs.Min(log => log.Latitude),
    W = logs.Min(log => log.Longitude),
    E = logs.Max(log => log.Longitude)
  };

では、LINQ の専門家の皆さん、データベースで多かれ少なかれこれを生成するには、上記をどのように記述すればよいでしょうか。

SELECT MIN(Latitude) S, MAX(Latitude) N, MIN(Longitude) W, MAX(Longitude) E
FROM ASSETLOG WHERE etc etc
4

2 に答える 2

1

もちろん、LINQ プロバイダーをだまして、最後までクエリを処理していると思わせるだけです。

  var logs = from asset in dc.Assets
             where asset.AssetId == assetId 
             let g = asset.AssetLogs
                 .Where(log => log.Recorded >= start && log.Recorded <= finish)
             select new GetInteractionBoundsResult
                 {
                     N = g.Max(log => log.Latitude),
                     S = g.Min(log => log.Latitude),
                     W = g.Min(log => log.Longitude),
                     E = g.Max(log => log.Longitude)
                 };
  return logs.Single();

Group By は、上記のクエリが生成する結合よりもパフォーマンスが良い場合があります。

  var logs = from log in dc.AssetLogs
             where log.AssetId == assetId &&
                 log.Recorded >= start && log.Recorded <= finish
             group log by log.AssetId into g
             select new GetInteractionBoundsResult
                 {
                     N = g.Max(log => log.Latitude),
                     S = g.Min(log => log.Latitude),
                     W = g.Min(log => log.Longitude),
                     E = g.Max(log => log.Longitude)
                 };
  return logs.Single();
于 2013-06-06T02:32:10.057 に答える
0

かなり洗練された LINQ プロバイダーが必要ですが、サブクエリが機能する場合があります。

  var res = from asset in dc.Assets
            where log.AssetId == assetId 
            let logs = (from AssetLog log in asset.AssetLogs
                        where log.Recorded >= start && log.Recorded <= finish
                        select log)
            select new GetInteractionBoundsResult()
            {
              N = logs.Max(log => log.Latitude),
              S = logs.Min(log => log.Latitude),
              W = logs.Min(log => log.Longitude),
              E = logs.Max(log => log.Longitude)
            };
  return res.Single();
于 2013-06-06T02:37:07.187 に答える