2014-12-31 9 views
7

Ich habe eine gespeicherte Prozedur, die 3 Eingabeparameter hat. Id und 2 VarChar-Bedingungen. Es funktioniert gut, wenn ich eine trockene Ausführung der gespeicherten Prozedur, aber wenn ich die gleiche gespeicherte Prozedur von meinem C# -Code aufrufen, schlägt es fehl. Ich übergebe genau die gleichen Parameter, die ich im Trockenlauf der gespeicherten Prozedur verwende, aber die gespeicherte Prozedur bleibt hängen.Stored Procedure funktioniert in DB, aber nicht in C# Code

Gibt es einen Grund dafür?

Ich verwende Express Edition von SQL Server 2008 R2.

Dies ist der Trockenlauf der gespeicherten Prozedur:

EXEC @return_value = [dbo].[GetAttributes] 
     @pi_PId = 95102, 
     @pi_returnOnly1stRow = 0, 
     @pi_returnExtAttr = 1 

SELECT 'Return Value' = @return_value 

Dies ist der Anruf aus dem C# -Code:

SqlDataAdapter da = new SqlDataAdapter(); 
da.SelectCommand = new SqlCommand("GetAttributes", conn); 
da.SelectCommand.Parameters.AddWithValue("@pi_PId", 95102); 
da.SelectCommand.Parameters.AddWithValue("@pi_returnOnly1stRow", 0); 
da.SelectCommand.Parameters.AddWithValue("@pi_returnExtAttr", 1); 
da.SelectCommand.CommandType = CommandType.StoredProcedure; 

DataSet ds = new DataSet(); 
da.Fill(ds, "result_name"); 
DataTable dt = ds.Tables["result_name"]; 
conn.Close(); 

EDIT: das Problem wieder ....

Ich dachte, ich hätte dieses Problem gelöst, indem ich die Prozesse, die dieses Problem verursacht haben, getötet habe, aber leider ist es zurückgekehrt. Nachdem ich gesagt habe, dass ich eine bessere und habe Verständnis des Problems und ich kann das Problem sehen, aber nicht sicher, was das verursacht.

Das Problem ist das gleiche. Stored Procedure läuft gut, wenn direkt auf dem SQL-Server ausgeführt, aber nicht ausgeführt werden, wenn von C# -Programm aufgerufen ....

Ich habe Sp_lock ausgeführt. Die gespeicherte Prozedur, die ich verwendet habe, hat die Spid: '59', für die die Sperren wie unten gezeigt sind. Ich weiß nicht, warum diese Tabellen nur gesperrt werden, wenn die Stored-Prozedur von C# aus aufgerufen wird und nicht während eines Trockenlaufs des SP.

59 2 0   0 DB [ENCRYPTION_SCAN]     S GRANT 
59 5 1802489500 0 PAG 1:169937       S GRANT 
59 5 1914489899 0 TAB          IS GRANT 
59 5 1898489842 0 TAB          IS GRANT 
59 5 1177771253 0 TAB          IS GRANT 
59 5 1786489443 0 TAB          IS GRANT 
59 5 1802489500 0 TAB          IS GRANT 
59 5 1882489785 0 TAB          IS GRANT 
59 5 0   0 DB          S GRANT 

AKTUELLE EDIT: Ich habe meine Sp bearbeiten auch in der SP mit NOLOCK auf jedem der Tabellen introdrucing beteiligt

ich bin auch die gespeicherte Prozedur hier für Ihre Referenz einfügen (mit neuesten NOLOCK) hinzugefügt ....

@pi_PId     INT 
, @pi_returnOnly1stRow BIT 
, @pi_returnExtAttr  BIT 
AS 

BEGIN 
    IF(@pi_returnOnly1stRow=1) 
     BEGIN 
      SELECT TOP 1 NULL section_name,header_mvoc.text Attr_Name, body_mvoc.Text Attr_Value,cds_mspecee.DisplayOrder 
      FROM cds_mspecee WITH (NOLOCK) 
      JOIN cds_mvocee header_mvoc WITH (NOLOCK)ON (cds_mspecee.hdrid = header_mvoc.id) 
      JOIN cds_mvocee body_mvoc WITH (NOLOCK) ON (cds_mspecee.bodyid = body_mvoc.id) 
      JOIN cds_prod WITH (NOLOCK)ON (cds_Prod.prodid = cds_mspecee.prodid) 
      JOIN ProductVariant revpro WITH (NOLOCK) On (revpro.ManufacturerSKU=cds_prod.mfpn) 
      AND revpro.ProductID = @pi_PId 
      UNION 
      SELECT section_evoc.Text section_name, header_evoc.text Attr_Name, body_evoc.Text Attr_Value, cds_Especee.DisplayOrder 
      FROM cds_Especee WITH (NOLOCK) 
      JOIN cds_Evocee section_evoc WITH (NOLOCK) ON (cds_Especee.SectID = section_evoc.ID) 
      JOIN cds_Evocee header_evoc WITH (NOLOCK) ON (cds_Especee.hdrid = header_evoc.id) 
      JOIN cds_Evocee body_evoc WITH (NOLOCK) ON (cds_Especee.bodyid = body_evoc.id) 
      JOIN cds_prod WITH (NOLOCK) ON (cds_Prod.prodid = cds_especee.prodid) 
      JOIN ProductVariant revpro WITH (NOLOCK) On (revpro.ManufacturerSKU=cds_prod.mfpn) 
      AND revpro.ProductID = @pi_PId 
      AND @pi_returnExtAttr = 1 
      ORDER BY section_name,displayorder ASC 
     END 
    ELSE 
     BEGIN 
      SELECT NULL section_name ,header_mvoc.text Attr_Name, body_mvoc.Text Attr_Value,cds_mspecee.DisplayOrder 
      FROM cds_mspecee WITH (NOLOCK) 
      JOIN cds_mvocee header_mvoc WITH (NOLOCK) ON (cds_mspecee.hdrid = header_mvoc.id) 
      JOIN cds_mvocee body_mvoc WITH (NOLOCK) ON (cds_mspecee.bodyid = body_mvoc.id) 
      JOIN cds_prod WITH (NOLOCK) ON (cds_Prod.prodid = cds_mspecee.prodid) 
      JOIN productVariant revpro WITH (NOLOCK) On (revpro.manufacturerSKU=cds_prod.mfpn) 
      AND revpro.ProductID = @pi_PId 
      UNION 
      SELECT section_evoc.Text section_name,header_evoc.text Attr_Name, body_evoc.Text Attr_Value,cds_Especee.DisplayOrder 
      FROM cds_Especee WITH (NOLOCK) 
      JOIN cds_Evocee section_evoc WITH (NOLOCK) ON (cds_Especee.sectid = section_evoc.id) 
      JOIN cds_Evocee header_evoc WITH (NOLOCK) ON (cds_Especee.hdrid = header_evoc.id) 
      JOIN cds_Evocee body_evoc WITH (NOLOCK) ON (cds_Especee.bodyid = body_evoc.id) 
      JOIN cds_prod WITH (NOLOCK) ON (cds_Prod.prodid = cds_especee.prodid) 
      JOIN productVariant revpro WITH (NOLOCK) On (revpro.manufacturerSKU=cds_prod.mfpn) 
      AND revpro.ProductID = @pi_PId 
      AND @pi_returnExtAttr = 1 
      ORDER BY section_name,displayorder ASC 
     END 
END 
+4

Bitte Postleitzahl für die gespeicherte Prozedur und Aufruf (beide SQL und C#) – SQLDiver

+3

Du bist eher eine Antwort bekommen, wenn Sie nach dem Code Sie verwenden beim Laufen/calling die gespeicherte Prozedur (sowohl für den Trockenlauf als auch in Ihrem C# -Code) –

+0

@MarsOne Bitte geben Sie einige spezifischere Informationen an. 1 - Verwenden Sie 'ADO.NET',' EF' oder etwas anderes auf 'C#' Seite. 2 - Der Code, den Sie versuchen auszuführen. 3 - der Fehler, den Sie bekommen. – Leron

Antwort

5

das klingt wie es ein Problem mit „Parameter Sniffing“ (http://blogs.technet.com/b/mdegre/archive/2012/03/19/what-is-parameter-sniffing.aspx) sein könnte, was bedeutet, dass der Ausführungsplan, die für Ihre Prozedur zwischengespeichert wird optimi sein könnte zed für verschiedene Parameterwerte basierend auf der vorherigen Ausführung der Prozedur. Dieser zwischengespeicherte Plan könnte für den Parameterwert x effizient sein, aber nicht für den Parameterwert y. Ich habe das gleiche Problem schon einmal gesehen, wo, wenn ich eine Abfrage in SSMS ausführe, es sofort ausgeführt wird, aber wenn ich von meiner App aus laufe, "hängt". Dies liegt daran, dass der Abfragetext bei der Ausführung in SSMS sich geringfügig von dem Abfragetext unterscheidet, der von der App stammt. Daher wird ein anderer zwischengespeicherter Ausführungsplan verwendet.

Eine Problemumgehung, um dieses Problem zu beheben, besteht darin, innerhalb Ihres Proc eine lokal begrenzte Variable zu erstellen, die als Kopie Ihrer Prozedurparameter fungiert.

ich auch empfehlen würde:

  1. Wenn Sie nicht über doppelte Zeilen aus jeder Seite der UNION zurück, ersetzen dann die UNION mit UNION ALL den nicht benötigten Aufwand für SQL Server zu entfernen, um doppelte Werte überprüft in Reihen.What is the difference between UNION and UNION ALL?
  2. Vermeiden Sie die Verwendung von WITH(NOLOCK) Hinweisen, da diese zu Datenkonsistenzproblemen führen können. Verwenden Sie diesen Hinweis nur, wenn Sie die Nebenwirkungen vollständig verstanden haben und Ihre Anwendung mit Dirty Reads in Ordnung ist und möglicherweise dieselbe Zeile mehrmals zurückgegeben hat (When should you use "with (nolock)").

Hier ist ein Beispiel das Feedback oben erwähnt enthält:

ALTER PROC dbo.usp_YourProcName 
    @pi_PId     INT 
, @pi_returnOnly1stRow BIT 
, @pi_returnExtAttr  BIT 
AS 
BEGIN 
    --these local variables are used to address "parameter sniffing" issues which may cause an ineffient plan cache. 
    --Use these local variables below instead of the direct parameter values. 
    DECLARE @local_pi_PId    INT = @pi_PId 
    , @local_pi_returnOnly1stRow BIT = @pi_returnOnly1stRow 
    , @local_pi_returnExtAttr  BIT = @pi_returnExtAttr 
    ; 

    IF(@local_pi_returnOnly1stRow=1) 
     BEGIN 
      SELECT TOP 1 NULL section_name,header_mvoc.text Attr_Name, body_mvoc.Text Attr_Value,cds_mspecee.DisplayOrder 
      FROM cds_mspecee 
      JOIN cds_mvocee header_mvoc ON (cds_mspecee.hdrid = header_mvoc.id) 
      JOIN cds_mvocee body_mvoc ON (cds_mspecee.bodyid = body_mvoc.id) 
      JOIN cds_prod ON (cds_Prod.prodid = cds_mspecee.prodid) 
      JOIN ProductVariant revpro On (revpro.ManufacturerSKU=cds_prod.mfpn) 
      AND revpro.ProductID = @local_pi_PId 
      UNION ALL 
      SELECT section_evoc.Text section_name, header_evoc.text Attr_Name, body_evoc.Text Attr_Value, cds_Especee.DisplayOrder 
      FROM cds_Especee 
      JOIN cds_Evocee section_evoc ON (cds_Especee.SectID = section_evoc.ID) 
      JOIN cds_Evocee header_evoc ON (cds_Especee.hdrid = header_evoc.id) 
      JOIN cds_Evocee body_evoc ON (cds_Especee.bodyid = body_evoc.id) 
      JOIN cds_prod ON (cds_Prod.prodid = cds_especee.prodid) 
      JOIN ProductVariant revpro On (revpro.ManufacturerSKU=cds_prod.mfpn) 
      AND revpro.ProductID = @local_pi_PId 
      AND @local_pi_returnExtAttr = 1 
      ORDER BY section_name,displayorder ASC 
     END 
    ELSE 
     BEGIN 
      SELECT NULL section_name ,header_mvoc.text Attr_Name, body_mvoc.Text Attr_Value,cds_mspecee.DisplayOrder 
      FROM cds_mspecee 
      JOIN cds_mvocee header_mvoc ON (cds_mspecee.hdrid = header_mvoc.id) 
      JOIN cds_mvocee body_mvoc ON (cds_mspecee.bodyid = body_mvoc.id) 
      JOIN cds_prod ON (cds_Prod.prodid = cds_mspecee.prodid) 
      JOIN productVariant revpro On (revpro.manufacturerSKU=cds_prod.mfpn) 
      AND revpro.ProductID = @local_pi_PId 
      UNION ALL 
      SELECT section_evoc.Text section_name,header_evoc.text Attr_Name, body_evoc.Text Attr_Value,cds_Especee.DisplayOrder 
      FROM cds_Especee 
      JOIN cds_Evocee section_evoc ON (cds_Especee.sectid = section_evoc.id) 
      JOIN cds_Evocee header_evoc ON (cds_Especee.hdrid = header_evoc.id) 
      JOIN cds_Evocee body_evoc ON (cds_Especee.bodyid = body_evoc.id) 
      JOIN cds_prod ON (cds_Prod.prodid = cds_especee.prodid) 
      JOIN productVariant revpro On (revpro.manufacturerSKU=cds_prod.mfpn) 
      AND revpro.ProductID = @local_pi_PId 
      AND @local_pi_returnExtAttr = 1 
      ORDER BY section_name,displayorder ASC 
     END 
END 
1

Starten Sie SQL Profiler und Code ausführen. Check hit kommt zu Profiler. Kopieren Sie von dort und führen Sie im Editor-Fenster, um Statistiken zu überprüfen.

0

Verwendung Dieses

SqlConnection con=new SqlConnection("ConnecttionString"); 
con.Open(); 
SqlCommand cmd = new SqlCommand("ProcedureName", con); 
cmd.CommandType = CommandType.StoredProcedure; 
cmd.Parameters.AddWithValue("StoredProcedureParameter", Value); 
SqlDataAdapter adp = new SqlDataAdapter(cmd); 
DataTable dt = new DataTable(); 
adp .Fill(dt); 
con.Close(); 
if (dt.Rows.Count > 0) 
{ 
// get the data table field value here 
} 
else 
{ 
// Table is Empty 
} 
Verwandte Themen