2

匿名型のこの単純なforeachループがあり、より効率的にする方法があるかどうか疑問に思っています。

155 個のアイテムをループすると、完了するまでに約 20 秒かかります。オブジェクトに設定されている他のプロパティのいくつかを省略しましたboAssetが、特別なことは何もありません - だけStrings/ Integers.

何かご意見は?

List<BoAsset> assetList = new List<BoAsset>();
foreach (var asset in result)
{
     BoAsset boAsset = new BoAsset();
     boAsset.Description = asset.Description;
     boAsset.DetailedDescription = asset.DetailedDescription;
     boAsset.AssetCustomerID = asset.AssetCustomerID;
     boAsset.AssetId = asset.AssetId;
     boAsset.Keywords = asset.Keywords;
     boAsset.Notes = asset.Notes;
     boAsset.Photographer = asset.Photographer;
     boAsset.PhotographerEmail = asset.PhotographerEmail;
     boAsset.Notes = asset.Notes;
     boAsset.Author = asset.Author;
     boAsset.FileName = asset.FileName;
     boAsset.FileExtension = asset.FileExtension;
     boAsset.AssetCreateDate = asset.AssetCreateDate;
     boAsset.AssetExpireDate = asset.AssetExpireDate;

     assetList.Add(boAsset);
}


var query =   (from a in context.Assets
              join subAf1 in context.AssetFiles on new { aid = a.AssetID, ftid = 1 } equals new { aid = subAf1.AssetID, ftid = subAf1.AssetTypeID } into theAf1
              from Af1 in theAf1.DefaultIfEmpty()
              join subAf2 in context.AssetFiles on new { aid = a.AssetID, ftid = 2 } equals new { aid = subAf2.AssetID, ftid = subAf2.AssetTypeID } into theAf2
              from Af2 in theAf2.DefaultIfEmpty()
              join subAf3 in context.AssetFiles on new { aid = a.AssetID, ftid = 3 } equals new { aid = subAf3.AssetID, ftid = subAf3.AssetTypeID } into theAf3
              from Af3 in theAf3.DefaultIfEmpty()
              join subAf4 in context.AssetFiles on new { aid = a.AssetID, ftid = 4 } equals new { aid = subAf4.AssetID, ftid = subAf4.AssetTypeID } into theAf4
              from Af4 in theAf4.DefaultIfEmpty()
              join subAf5 in context.AssetFiles on new { aid = a.AssetID, ftid = 5 } equals new { aid = subAf5.AssetID, ftid = subAf5.AssetTypeID } into theAf5
              from Af5 in theAf5.DefaultIfEmpty()
              join subFp in context.FilePaths on new { fpid = Af1.FilePathID } equals new { fpid = subFp.FilePathID } into theFp1
              from fp1 in theFp1.DefaultIfEmpty()
              //join fp in context.FilePaths on Af1.FilePathID equals fp.FilePathID

              where a.AssetCustomerID == custId && a.AssetID == assetId
              select new { a, Af1, Af2, Af3, Af4, Af5, fp1 }).Distinct();

var result =   from q in query
               select new
               {
                   AssetId = q.a.AssetID,
                   AssetCustomerId = q.a.AssetCustomerID,
                   StockImage = q.a.StockImage,
                   Description = q.a.Description,
                   DetailedDescription = q.a.DetailedDescription,
                   Author = q.a.Author,
                   FileName = q.Af1.FileName, //was 1
                   FileExtension = q.Af1.FileExtension, //was 1
                   AssetCreateDate = q.a.AssetCreateDate,
                   AssetExpireDate = q.a.AssetExpireDate,
                   AssetActivateDate = q.a.AssetActivateDate,

                   Notes = q.a.Notes,
                   Keywords = q.a.Keywords,
                       Photographer = q.a.Photographer,
                       PhotographerEmail = q.a.PhotographerEmail
               }
4

2 に答える 2

2

特に使用されていないものがいくつかあることを考えると、クエリが複雑すぎる(結合が多すぎる)と思います。

一部の LINQ プロバイダー (LINQ to Entities など) では、クエリが複雑な場合、単にクエリ ツリーを処理して SQL に変換するのにかなりの時間がかかる場合があることに注意してください。(私はすでに、EF が分析するのに 10 秒または 15 秒かかるクエリをいくつか持っています。)

私が思うに、使用している LINQ 実装がデータベースにヒットしている場合は、SQL プロファイリング ツールを使用して、サーバーに渡されている実際の SQL と、その SQL のパフォーマンスを確認します。

foreachまた、使用しているフィールドを考えると、結果を直接BoAssetオブジェクトに具体化することで、実際にループをなくすことができることに注意してください。

あれは:

var result = from q in query
             select new BoAsset
             {
                 AssetId = q.a.AssetID,
                 AssetCustomerId = q.a.AssetCustomerID,
                 StockImage = q.a.StockImage,
                 Description = q.a.Description,
                 DetailedDescription = q.a.DetailedDescription,
                 Author = q.a.Author,
                 FileName = q.Af1.FileName, //was 1
                 FileExtension = q.Af1.FileExtension, //was 1
                 AssetCreateDate = q.a.AssetCreateDate,
                 AssetExpireDate = q.a.AssetExpireDate,
                 AssetActivateDate = q.a.AssetActivateDate,
                 Notes = q.a.Notes,
                 Keywords = q.a.Keywords,
                 Photographer = q.a.Photographer,
                 PhotographerEmail = q.a.PhotographerEmail
             };

List<BoAsset> assetList = result.ToList();
于 2013-01-25T20:45:58.520 に答える
2

155 個のオブジェクトを作成してデータをコピーするのにかかる時間は、ミリ秒程度です。そのコードに対して、大幅な (または顕著な) 改善を行うためにできることは何もありません。

いつでも保存したい場合は、結果を作成するクエリを確認する必要があります。時間がかかっているということです。

于 2013-01-25T18:44:54.017 に答える