2009-08-28 9 views
13

Ich entschied mich, kein Orm zu verwenden und gerade ADO.NET für mein Projekt zu verwenden. Ich weiß, ich weiß, dass es länger dauern wird, um zu programmieren, aber ich möchte nur, dass Seiten mit hohen Geschwindigkeiten geladen werden, selbst zu Spitzenzeiten.C# - Was sind einige High Performance Best Practices/Tipps für ADO.NET

+0

Welche Datenbank (ich nehme SQL Server an)? – MusiGenesis

+0

Ich würde eine vorzeitige Optimierung vermeiden. – Alex

+6

+1 für die Verwendung * plain alt * ADO.NET :) –

Antwort

9

Ein Fehler, den ich sehe immer und immer wieder:

Instanziieren und Einrichten alles (DbConnection, DbCommand, DbParameters) innerhalb einer Methode, die immer wieder in einer engen Schleife genannt wird.

In den meisten Fällen können Sie diese lokalen Variablen als Klassenmitglieder umstellen, indem Sie sie nur einmal instanziieren und nur die Aktualisierungen für DbParameters innerhalb der Methode beibehalten.


AKTUALISIERT für in den Kommentaren

Haftungsausschluss gefragt Beispielcode enthalten: für den alleinigen Absicht zu demonstrieren, den Punkt zu bewegen wiederholende Sachen aus der Schleife Dies ist eine kurze montierte Probe . Andere bessere Praktiken werden nicht unbedingt implementiert.


     public static void Show() { 
      List people = new List(); 

      //Everything is done inside the loop 
      PersonDal personDal = new PersonDal(); 
      foreach (Person person in people) { 
       personDal.Insert(person); 
      } 

      //Things are setup once outside the loop. 
      using (DbConnection connection = SqlClientFactory.Instance.CreateConnection()) { 
       // setup the connection 
       BetterPersonDal betterPersonDal = new BetterPersonDal(connection); 
       connection.Open(); 
       foreach (Person person in people) { 
        betterPersonDal.Insert(person); 
       } 
      } 
     } 
    } 

    class Person { 
     public int Id { get; set; } 
     public string Name { get; set; } 
    } 

Auf dieser ersten Implementierung wird alles, was jedes Mal das Verfahren eingestellt wird aufgerufen:


class PersonDal { 
    public int Insert(Person person) { 
     DbProviderFactory factory = SqlClientFactory.Instance; 

     using (DbConnection connection = factory.CreateConnection()) { 
      connection.Open(); 

      connection.ConnectionString = "Whatever"; 

      using (DbCommand command = connection.CreateCommand()) { 
       command.CommandText = "Whatever"; 
       command.CommandType = CommandType.StoredProcedure; 

       DbParameter id = command.CreateParameter(); 
       id.ParameterName = "@Id"; 
       id.DbType = DbType.Int32; 
       id.Value = person.Id; 

       DbParameter name = command.CreateParameter(); 
       name.ParameterName = "@Name"; 
       name.DbType = DbType.String; 
       name.Size = 50; 
       name.Value = person.Name; 

       command.Parameters.AddRange(new DbParameter[] { id, name }); 

       return (int)command.ExecuteScalar(); 
      } 
     } 
    } 
} 

Jetzt bewegen wir uns um die Einrichtung der Bauobjekte es aus der Schleife zu verlassen:


class BetterPersonDal { 
    private DbProviderFactory factory; 
    private DbConnection connection; 
    private DbCommand command; 
    private DbParameter id; 
    private DbParameter name; 

    public BetterPersonDal(DbConnection connection) { 
     this.command = connection.CreateCommand(); 
     this.command.CommandText = "Whatever"; 
     this.command.CommandType = CommandType.StoredProcedure; 

     this.id = command.CreateParameter(); 
     this.id.ParameterName = "@Id"; 
     this.id.DbType = DbType.Int32; 

     this.name = command.CreateParameter(); 
     this.name.ParameterName = "@Name"; 
     this.name.DbType = DbType.String; 
     this.name.Size = 50; 

     this.command.Parameters.AddRange(new DbParameter[] { id, name }); 
    } 

    public int Insert(Person person) { 
     this.id.Value = person.Id; 
     this.name.Value = person.Name; 

     return (int)command.ExecuteScalar(); 
    } 
} 

+0

Enthaltenes Beispiel –

4

Werfen Sie einen Blick auf das Improving .NET Application Performance and Scalability Buch (online kostenlos verfügbar, in MSDN). Es gibt eine whole chapter über die Verbesserung der ADO.NET-Leistung.

+0

Ausgezeichnete Links. Die einzige Sache, der ich nicht zustimmen würde, ist ihre Betonung auf die Verwendung gespeicherter Prozeduren für die Leistung. Wie ich es verstehe, zwischenspeichern moderne Versionen von SQL Server die Ausführungspläne für Ad-hoc-SQL-Abfragen, so dass eine Ad-hoc-Abfrage einmal ausgeführt werden sollte, sobald sie so schnell wie eine gespeicherte Prozedur sein sollte. Der verknüpfte Artikel stammt jedoch tatsächlich von Microsoft, daher werde ich nicht behaupten, dass ich es besser weiß als sie. Bei all dem Benchmarking, das ich in letzter Zeit durchgeführt habe, ist die Performance von gespeicherten Prozeduren und Ad-hoc-Abfragen jedoch praktisch identisch. – MusiGenesis

+1

Ein sehr gutes Buch in der Tat. Ich habe eine gedruckte Version davon. Leider wurde es seit 2004 nicht aktualisiert und viele Dinge haben sich geändert. Der Back-Store von DataRow zum Beispiel wurde komplett in .Net 2.0 neu geschrieben, was das Leistungsprofil der Verwendung von DataSets zwischen den Versionen 1.x und 2.0 dramatisch veränderte. –

2

über Verbindungsmanagement sehr smart. Das Öffnen einer DB-Verbindung kann sehr teuer sein. Versuchen Sie dies beim Schreiben der Datenbankzugriffsebene zu beachten.

+4

Dies sollte nicht wirklich ein Problem sein, solange Verbindungspooling aktiviert ist. Wenn ein Verbindungsobjekt instanziiert wird und seine 'Open'-Methode aufgerufen wird, wird in der Regel nur eine verfügbare Verbindung aus dem Pool abgerufen, anstatt eine vollständig neue Verbindung zur Datenbank herzustellen. – LukeH

+2

Mit Lukas einverstanden. Verbindungen waren (mehr) seit mehr als 10 Jahren nicht wichtig. – MusiGenesis

+0

Ich habe einen Legacy-Code in VB.Net geschrieben, der alles gemischt hat, wie wenn es in VB6 geschrieben wäre: keine Ebenen, keine Klassen, alle Codes innerhalb des Formulars und die Basismodule ... –

1

Wenn Sie kein ORM verwenden, werden Sie Ihre Daten auch nicht zwischenspeichern? Das ist ein großer Vorteil der Verwendung eines ORM. Wenn kein Datencache vorhanden ist, müssen Sie nach Wegen zum Zwischenspeichern von HTML/JavaScript suchen. Dies kann mithilfe der OutputCache-Direktive und SqlDependency erreicht werden. Oder indem Sie statische HTML- und JavaScript-Dateien veröffentlichen. In beiden Fällen können Sie höhere Belastungen bewältigen, wenn Sie nicht ständig bei jeder Anfrage auf die Datenbank zugreifen.

Einige Links:

ASP.NET Web Site Performance Improvement http://www.codeproject.com/KB/aspnet/aspnetPerformance.aspx

10 ASP.NET Leistung und Skalierbarkeit Secrets http://www.codeproject.com/KB/aspnet/10ASPNetPerformance.aspx

Omar AL Zabir Blog auf ASP.NET Ajax und .NET 3.5 http://msmvps.com/blogs/omar/archive/tags/performance/default.aspx

1

Der Artikel, den Martin verlinkt, ist ausgezeichnet. Ich würde nur hinzufügen, dass Sie definitiv einen DataReader anstelle eines DataSet verwenden möchten (ich liebe DataSets, aber nicht aus Leistungsgründen).

+0

Es sei denn, du musst zurückgehen Frühere Datensätze, bei denen die Verwendung eines DataSets eine gute Idee sein kann. –

+0

@Alfred: Er sagte, er wolle [s] Seiten mit hoher Geschwindigkeit laden, also nehme ich an, dass er über ASP.Net spricht. In diesem Fall würde es einem Benutzer ermöglichen, zu vorherigen Datensätzen in einem DataSet zurückzukehren, um das DataSet zwischenzuspeichern, was wahrscheinlich keine gute Idee wäre. – MusiGenesis

+0

@MusiGenesis: Ich stimme dir nicht zu. Sie sagten, Sie lieben DataSets und ich gebe ein Beispiel dafür, wann sie geeignet sind. Selbst auf einer * super duper * -Hochgeschwindigkeitswebseite könnte jemand Logik haben, die aus irgendwelchen geschäftlichen Gründen Zugriff auf frühere Datensätze benötigt. Verwenden Sie ein DataSet statt zurück zu der Datenbank. Keine DataSets im Cache - nichts. Nur ein DataSet wird während der Lebensdauer der Anfrage verwendet. –

Verwandte Themen