1

結果をループして Xelement を作成しようとすると、linq クエリが遅くなり、後で XElement に基づいて XSLT を処理します。

これが私のコードです

public override XElement Search(SearchCriteria searchCriteria)
    {
        XElement root = new XElement("Root");
        using (ReportOrderLogsDataContext dataContext = DataConnection.GetLinqDataConnection<ReportOrderLogsDataContext>(searchCriteria.GetConnectionString()))
        {
            try
            {


                IQueryable<vw_udisclosedDriverResponsePart> results = from a in dataContext.vw_udisclosedDriverResponseParts
                              where
                                  (a.CreateDt.HasValue &&
                                   a.CreateDt >= Convert.ToDateTime(searchCriteria.BeginDt) &&
                                   a.CreateDt <= Convert.ToDateTime(searchCriteria.EndDt))
                              select a;

                if (!string.IsNullOrEmpty(searchCriteria.AgentNumber))
                {
                    results = results.Where(request => request.LgAgentNumber == searchCriteria.AgentNumber);
                }
                if (!string.IsNullOrEmpty(searchCriteria.AgentTitle))
                {
                    results = results.Where(a => a.LgTitle == searchCriteria.AgentTitle);
                }
                if (!string.IsNullOrEmpty(searchCriteria.QuotePolicyNumber))
                {
                    results = results.Where(a => a.QuotePolicyNumber == searchCriteria.QuotePolicyNumber);
                }
                if (!string.IsNullOrEmpty(searchCriteria.InsuredName))
                {
                    results = results.Where(a => a.LgInsuredName.Contains(searchCriteria.InsuredName));
                }

                foreach (var match in results) // goes slow here, specifically times out before evaluating the first match when results are too large.
                {
                    DateTime date;
                    string strDate = string.Empty;
                    if (DateTime.TryParse(match.CreateDt.ToString(), out date))
                    {
                        strDate = date.ToString("MM/dd/yyyy");
                    }

                    root.Add(new XElement("Record",
                                          new XElement("System", "Not Supported"),
                                          new XElement("Date", strDate),
                                          new XElement("Agent", match.LgAgentNumber),
                                          new XElement("UserId", match.LgUserId),
                                          new XElement("UserTitle", match.LgTitle),
                                          new XElement("QuoteNum", match.QuotePolicyNumber),
                                          new XElement("AddressLine1", match.AddressLine1),
                                          new XElement("AddressLine2", match.AddressLine2),
                                          new XElement("City", match.City),
                                          new XElement("State", match.State),
                                          new XElement("Zip", match.Zip),
                                          new XElement("DriverName", string.Concat(match.GivenName, " ", match.SurName)),
                                          new XElement("DriverLicense", match.LicenseNumber),
                                          new XElement("LicenseState", match.LicenseState)));
                    ;
                }
            }
            catch (Exception es)
            {

                throw es;
            }
        }
        return root;
        // return GetSearchedCriteriaFromStoredPocedure(searchCriteria);
    }

結果オブジェクトを XElement に変換するより良い方法があると思います。ビュー自体の処理には約 2 秒しかかかりません。多くの結果が返されない場合でも、結果オブジェクトをループしようとすると、タイムアウトが発生します。

どんな助けでも大歓迎です。

ありがとう!

-ジェームズ

2012 年 7 月 10 日修正

問題はlinqクエリ自体ではなく、日付範囲を指定するときのビューの実行にあります。ビュー自体を実行すると、約 4 ~ 6 秒かかります。短い日付範囲 (2012 年 7 月 5 日から 2012 年 7 月 10 日) を使用すると、ビューは約 1:30 になります。指定された日付範囲でクエリのパフォーマンスを向上させる方法について誰か提案がありますか? すべての結果を取得し、それらをループして日付を確認すると、より高速になります。

すなわち

    IQueryable<vw_udisclosedDriverResponsePart> results = from a in dataContext.vw_udisclosedDriverResponseParts select a;

                foreach (var match in results) //results only takes 3 seconds to enumerate, before would timeout
                {
                    // eval search criteria date here.
                }

上記で提案したようにコーディングできますが、より良い方法はありますか?

4

3 に答える 3

2

データベースはどのように機能しますか? 最も簡単なテストは、サンプル クエリ (データベースから必要なデータを取得するクエリ) を実行して、データベースのインデックス作成とパフォーマンスをテストすることです。これは、99% のケースで速度低下の原因となるためです。

遅延が発生していると思います

  • 前もってすべての行を取得するのではなく、データベースから繰り返し処理している。
  • 悪い条件で選択していWHEREます (インデックスは正しいですか?)

まず、結果を取得するために呼び出しToListて、遅延が XML 構造ではなくデータベースで発生していることを確認します。

if (!string.IsNullOrEmpty(searchCriteria.InsuredName))
{
    //...
}    
var matches = results.ToList();    
foreach (var match in matches) 
{
    //...

var matches = results.ToList()が非常に遅いと仮定すると、WHERE節の関数を調べます

(a.CreateDt.HasValue &&
a.CreateDt >= Convert.ToDateTime(searchCriteria.BeginDt) &&
a.CreateDt <= Convert.ToDateTime(searchCriteria.EndDt))

すべての行に対して実行されていないことを確認します。

SQL Server を使用している場合は、([ツール] メニューで) プロファイラーを実行して、LINQ-to-SQL の SQL をトレースします。

于 2012-07-09T22:40:59.007 に答える
1

いくつかの実験をお勧めします:

1。
置く

int count = results.Count();

foreachの前に、これに時間がかかるかどうかを確認します。

二。
Count ()呼び出しを終了し、foreachがまだ遅いかどうかを確認します。速い場合は、データベースへの最初の接続が遅いことを示唆しています。

他の人が示唆したように、クエリがデータベースでどのように実行されるかを見てください(実際には、C#を使用せずにデータベースに入力します)。

また、SHOW TABLE の結果を投稿して、コミュニティがインデックスを検査し、修正を支援できるようにすることもできます。

于 2012-07-10T07:47:10.377 に答える
1

もちろん、linq の外で変換を行います。条件は、Linq 式の実行中に変更されません。

あなたが投稿したものから、私はこの例を作りました:

var begin = Convert.ToDateTime(searchCriteria.BeginDt);
var end = Convert.ToDateTime(searchCriteria.EndDt);

var results = from a in searchList
              where ((a.CreateDt.HasValue &&
                      a.CreateDt >= begin &&
                      a.CreateDt <= end)
                      && (string.IsNullOrEmpty(searchCriteria.AgentNumber) || a.LgAgentNumber == searchCriteria.AgentNumber)
                      && (string.IsNullOrEmpty(searchCriteria.AgentTitle) || a.LgTitle == searchCriteria.AgentTitle)
                      && (string.IsNullOrEmpty(searchCriteria.QuotePolicyNumber) || a.LgTitle == searchCriteria.QuotePolicyNumber)
                      && (string.IsNullOrEmpty(searchCriteria.InsuredName) || a.LgInsuredName.Contains(searchCriteria.InsuredName))
                     )
                        select a;

おそらくこれはあなたにとって役に立ちます。

時間を測定するために、私は以下を使用しました:

var watch = new Stopwatch();
watch.Start();
var arr = results.ToArray();  // force evaluation of linq
watch.Stop();
var elapsed = watch.ElapsedTicks;

変更されたクエリは、すでに平均で約 30 ~ 40% 高速になっているようですが、いくつか実行しただけです。

于 2012-07-09T20:16:32.927 に答える