2016-06-13 10 views
0

Ich habe diese Methode # 1 Abfrage unten, die mit Dapper parametrisiert ist, Problem ist die Abfrage Zeit mit dieser Ansatz auch nach 30 Sekunden und normalerweise dauert es maximal 1 Sekunde auf SSMS mit Plain SQL.Dapper parametrisierte Abfrage nach String-Wert verursacht Probleme?

Allerdings funktioniert Methode # 2-Abfrage tatsächlich, wo die Abfrage auf der Serverseite anstelle von parametrisierten erstellt wird. Eine Sache, die ich bemerkt habe, ist, es könnte etwas mit Filter für Vorname und Nachname zu tun haben, ich habe einzelne Quote auf Methode # 2 für diese Filter, aber nicht für Methode # 1.

Was ist falsch an Methode # 1?

Method # 1 

string query = "SELECT * 
       FROM dbo.Customer c     
       WHERE c.MainCustomerId = @CustomerId 
       AND (@IgnoreCustomerId = 1 OR c.CustomerID = @FilterCustomerId) 
       AND (@IgnoreFirstName = 1 OR c.FirstName = @FilterFirstName) 
       AND (@IgnoreLastName = 1 OR c.LastName = @FilterLastName) 
       AND (@IgnoreMemberStatus = 1 OR c.CustomerStatusID = @FilterMemberStatus) 
       AND (@IgnoreMemberType = 1 OR c.CustomerTypeID = @FilterMemberType) 
       AND (@IgnoreRank = 1 OR c.RankID = @FilterRank) 
       ORDER BY c.CustomerId 
       OFFSET @OffSet ROWS 
       FETCH NEXT 50 ROWS ONLY";  



       _procExecutor.ExecuteSqlAsync<Report>(query, new 
      { 
       CustomerId = customerId, 
       IgnoreCustomerId = ignoreCustomerId, 
       FilterCustomerId = filter.CustomerID, 
       IgnoreFirstName = ignoreFirstName, 
       FilterFirstName = filter.FirstName, 
       IgnoreLastName = ignoreLastName, 
       FilterLastName = filter.LastName, 
       IgnoreMemberStatus = ignoreMemberStatus, 
       FilterMemberStatus = Convert.ToInt32(filter.MemberStatus), 
       IgnoreMemberType = ignoreMemberType, 
       FilterMemberType = Convert.ToInt32(filter.MemberType), 
       IgnoreRank = ignoreRank, 
       FilterRank = Convert.ToInt32(filter.Rank), 
       OffSet = (page - 1) * 50 
      }); 


    Method # 2  

      string queryThatWorks = 
          "SELECT * 
       FROM dbo.Customer c     
       WHERE c.MainCustomerId = @CustomerId 
       AND ({1} = 1 OR c.CustomerID = {2}) 
       AND ({3} = 1 OR c.FirstName = '{4}') 
       AND ({5}= 1 OR c.LastName = '{6}') 
       AND ({7} = 1 OR c.CustomerStatusID = {8}) 
       AND ({9} = 1 OR c.CustomerTypeID = {10}) 
       AND ({11} = 1 OR c.RankID = {12}) 
       ORDER BY c.CustomerId 
       OFFSET {13} ROWS 
       FETCH NEXT 50 ROWS ONLY"; 

       _procExecutor.ExecuteSqlAsync<Report>(string.Format(queryThatWorks, 
       customerId, 
       ignoreCustomerId, 
       filter.CustomerID, 
       ignoreFirstName, 
       filter.FirstName, 
       ignoreLastName, 
       filter.LastName, 
       ignoreMemberStatus, 
       Convert.ToInt32(filter.MemberStatus), 
       ignoreMemberType, 
       Convert.ToInt32(filter.MemberType), 
       ignoreRank, 
        Convert.ToInt32(filter.Rank), 
       (page - 1) * 50 
       ), null); 
+0

Wissen Sie, wie Sie den Ausführungsplan XML zu bekommen? Wenn ja, poste es. Das ist immer der erste Schritt, wenn man versucht, so etwas herauszufinden. –

+0

da eine Abfrage über Dapper parametrisiert ist, ist ein anderer SQL-Befehl, ich könnte einen Ausführungsplan für Plain SQL bekommen (aber das läuft schnell). Für parmeterized bin ich nicht sicher, ob ich einen Ausführungsplan erstellen kann –

+0

Um den Ausführungsplan für Dapper zu erhalten, verwenden Sie das SQL Profiler-Tool. Dies erfasst die tatsächliche SQL, die an die Datenbank gesendet wird. Von dort können Sie es in SSMS einfügen und den Plan wie gewohnt erhalten. –

Antwort

1

Ich habe das schon unzählige Male gesehen.

Ich wette, dass Ihre Spalten varChar sind, aber Dapper sendet Ihre Parameter als nVarChar. Wenn das geschieht, muss SQL Server eine Konvertierung für den Wert ausführen, der in jeder einzelnen Zeile gespeichert wird. Abgesehen davon, dass es sehr langsam ist, verhindert dies die Verwendung von Indizes.

Siehe "Ansi Strings und varchar" in https://github.com/StackExchange/dapper-dot-net

+0

Dammm du hattest Recht !! –

+0

Deshalb erstelle ich meine eigene ORM, Tortuga Chain. Es wird automatisch erkannt, welcher Parametertyp für normale Abfragen verwendet werden soll. –

Verwandte Themen