SqlParameter.Add() vs AddWithValue()

Posted in C#, SQL Server on Juni 21st, 2010 by Andreas Schwarz

Der Großteil der Entwickler wird sich bei Datenbankabfragen sicher mit der Methode AddWithValue() angefreundet haben.

Man gibt nur noch den Namen des Sql-Parameters und den entsprechenden Wert an und das .Net Framework kümmert sich um den Rest.

using (var conn = new SqlConnection(@"ConnectionString zensiert"))
{
     conn.Open();

     string sql = "Select LastName FROM TestTable WHERE LastName = @l";

     var cmd = new SqlCommand(sql, conn);

      cmd.Parameters.AddWithValue("@l", "Harglgargl");
       //selbes Ergebnis
       //cmd.Parameters.Add("@l", "Meier");

       object res = cmd.ExecuteScalar();
}

Ich würde erwarten, dass der SQL-Server schlau genug wäre und den Parameter korrekt auflöst.

Leider gibt es hier ein kleines Problem.

Führt man das Codefragment mit den Werten “Huber”, “Schmidt”, und “Harglgargl” aus würde man erwarten,

dass der SQL-Server einen bereits vorhandenen Ausführungsplan benutzt bzw. einen Plan für diese Abfrage erstellt und dann wiederverwendet.

Das Resultat sieht leider etwas anders aus:

Cached Plans

Für jede Varchar-Länge wird ein eigener Ausführungsplan angelegt.

Die Auswirkungen werden bei einem genaueren Blick auf die Speicherausnutzung des SQL-Servers deutlich.

Mein Dev-Server sagt dazu auf jeden Fall Folgendes:

Cached: verwendeter Speicher um Seiten zu cachen

Stolen: Speicher der “gestohlen” wird um Ausführungspläne zu cachen

Das Verhältnis wird in den meisten Szenarien vernachlässigbar sein. Ich kann mir allerdings einige Umgebungen vorstellen in denen das Ganze zum Problem werden könnte.

Wie dem auch sei. Je mehr Speicher zur Verfügung steht um Seiten zu cachen umso besser :)

Die Lösung des Ganzen ist aktuell leider etwas umständlich. Man kann das Ganze umgehen indem man den Datentyp der entsprechenden Datenbankspalte angibt.

Leider ist das Ganze extrem lästig da es aktuell keine brauchbare Überladung gibt (Man kann sich natürlich eine schnitzen)…

using (var conn = new SqlConnection(@"ConnectionString zensiert"))
{
     conn.Open();

     string sql = "Select LastName FROM TestTable WHERE LastName = @l";

     var cmd = new SqlCommand(sql, conn);

     SqlParameter p = new SqlParameter("@l", System.Data.SqlDbType.VarChar, 1000);
     p.Value = "Huber";

     cmd.Parameters.Add(p);

     object res = cmd.ExecuteScalar();
}

 

Tags: , , ,

Hierarchische Gruppierungen mit Rank()

Posted in SQL Server on Mai 23rd, 2010 by Andreas Schwarz

Wie ermittelt man die Torschützenkönige der Bundesliga aus einer Liste aller Torschützen der jeweiligen Saison ?

Das Ganze wäre prinzipiell mit Hilfe einiger Subqueries machbar.

Optimaler läßt sich das Ganze mit Hilfe der Funktion Rank() lösen die ab SQL-Server 2005 zur Verfügung steht.

SELECT
	Spieler,
	Verein,
	Tore,
	Saison,
	RANK() OVER (PARTITION BY Saison ORDER BY Tore DESC) AS Platz
FROM
	#ErzielteTreffer

SELECT Spieler,Verein,Tore,Saison FROM
	(
	SELECT
		Spieler,
		Verein,
		Tore,
		Saison,
		RANK() OVER (PARTITION BY Saison ORDER BY Tore DESC) AS Platz
	FROM
	#ErzielteTreffer
	) AS Rangfolge
WHERE Platz = 1

Tags:

Custom WCF Username/Password Validator mit wsHttpBinding

Posted in Allgemein, C# on April 16th, 2010 by Andreas Schwarz
...
namespace WCFTestService.Auth
{
    public class CustomUserNamePasswordValidator : UserNamePasswordValidator
    {
        public override void Validate(string userName, string password)
        {
               // check credentials here...
...

Config:


...
    
      
        
          ...
          

              
            
            
          
        
      
    
    
      
        
          
            
            
          
          ...
      
    
    
      
        
      
    
    ...

Tags: , ,

Custom WCF MSMQ-Tracer

Posted in Allgemein on November 30th, 2009 by Andreas Schwarz

WCF Custom MSMQ Tracer – Sample

Das Standard-Traceing im WCF Framework ist erstaunlich einfach anzuwenden und zu konfigurieren. Auch das im Framework enthaltene Analysetool ist ganz brauchbar.

So viel Luxus ist man gar nicht gewohnt wenn man vorher hauptsächlich mit dem WSE-Framework zu tun hatte…

Leider ist Microsoft den Weg nicht komplett zu Ende gegangen. Gibt man sich nicht mit der Erzeugung von Logdateien zufrieden, sondern will das Ganze in eine Datenbank  bzw. Message Queue persistieren darf man wieder selbst tätig werden.

Ich würde davon abraten das komplette Traceing direkt synchron aufzusetzen. Es hat sich bewährt die Nachrichten zuerst einmal zwischenzulagern und die Verarbeitung dann asynchron auszuführen.

public class MsmqTracer : TraceListener
{
   public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
   {
   if (!string.IsNullOrEmpty(traceQueue))
   {
      try
      {
      MessageQueue msmq = new MessageQueue(traceQueue);
      MessageQueueTransaction trans = new MessageQueueTransaction();

      trans.Begin();
      Message msg = new Message(data.ToString(), new XmlMessageFormatter());

      msmq.Send(msg, trans);
      trans.Commit();
      }

      catch (Exception msmqEx)
      {
         Debug.WriteLine(string.Format("Error while persisting trace: {0}", msmqEx.ToString()));
      }
   }
   else
   {
      Debug.WriteLine("Missing MSMQ Trace");
   }
}

public override void Write(string message) {}

public override void WriteLine(string message) {}


  

 
Tags: , ,

WCF Performance Counter

Posted in Allgemein on November 30th, 2009 by Andreas Schwarz

Das WCF-Framework stellt eine Unzahl an Meßwerten zur Verfügung.

Leider ist das Ganze kaum dokumentiert…

Die Aktivierung der Counter ist denkbar einfach (wenn man mal rausgefunden hat dass es sowas überhaupt gibt…) und erfolgt durch einen Eintrag in der App.Config des Hosts

PerfCountersConfig

Die entsprechenden Werte lassen sich dann direkt mit perfmon anzeigen und auswerten.

perfmon1

perfmon2

Tags: ,