2014-12-31 11 views
7

mam procedur przechowywanych, który ma 3 parametry wejściowe. Id, i 2 warunki VarChar. Działa to dobrze, gdy wykonuję suchy przebieg procedury przechowywanej, ale gdy wywołuję tę samą procedurę przechowywaną z mojego kodu C#, to się nie powiedzie. Przepuszczam dokładnie te same parametry, których używam w trybie suchym procedury przechowywanej, ale procedura przechowywana pozostaje zwisająca.przechowywane procedura działa w bazie danych, ale nie jest w kod C#

Czy istnieje jakikolwiek powód, aby tak się stało?

Używam SQL Server 2008 R2 edycja Express.

To jest sucho procedury przechowywanej:

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

SELECT 'Return Value' = @return_value 

Jest to wezwanie z kodu C#:

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: Problem Zwraca ....

Myślałem, że rozwiązałem ten problem, zabijając proces, który spowodował ten problem, ale niestety powrócił. Powiedział, że mam lepsze Zrozumienie problemu i widzę problem, ale nie jestem pewien, co to powoduje.

Problem jest taki sam. Procedura przechowywana działa dobrze, jeśli uruchomić bezpośrednio na serwerze SQL, ale nie wykona, gdy wywołana z C# programu ....

Pobiegłem sp_lock. Zastosowana procedura przechowywana ma Spid: "59", dla którego zamki są pokazane poniżej. Nie wiem, dlaczego te tabele zostaną zablokowane tylko wtedy, gdy procedura składowana jest wywoływana z poziomu C#, a nie kiedy podczas suchego uruchomienia 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 

NAJNOWSZE EDIT: Mam również edytowane mój Sp przez introdrucing Z NOLOCK na każdej z tabel zaangażowanych w SP

Ja również wklejenie procedury przechowywanej tutaj dla odniesienia (z najnowszym NOLOCK dodana) ....

@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

kod proszę pisać procedury składowane i inwokacji (zarówno sql i C#) – SQLDiver

+3

jesteś bardziej prawdopodobne, aby uzyskać odpowiedź, jeśli pisać kod, którego używasz podczas pracy/nazywając procedura składowana (zarówno w trybie suchym, jak i w kodzie C#) –

+0

@MarsOne Podaj bardziej szczegółowe informacje. 1 - Czy używasz 'ADO.NET',' EF' lub czegoś innego na stronie 'C#'. 2 - Kod, który próbujesz wykonać. 3 - błąd, który otrzymujesz. – Leron

Odpowiedz

5

brzmi to jak to może być problem z „parametr wąchania” (http://blogs.technet.com/b/mdegre/archive/2012/03/19/what-is-parameter-sniffing.aspx), co oznacza, że ​​plan realizacji, które są buforowane dla procedury może być Optimi zed dla różnych wartości parametrów na podstawie wcześniejszego wykonania procedury. Ten buforowany plan może być wydajny dla wartości parametru x, ale nie dla wartości parametru y. Napotkaliśmy ten sam problem wcześniej, gdzie, gdy uruchamiam zapytanie w SSMS, działa natychmiast, ale jeśli uruchamiam z mojej aplikacji, to "zawiesza się". Dzieje się tak dlatego, że tekst zapytania, gdy uruchamiam w SSMS, jest nieco inny niż tekst zapytania pochodzący z aplikacji, więc używa innego buforowanego planu wykonania.

Jeden obejście rozwiązać ten problem jest do tworzenia zmiennych o zasięgu lokalnym w swoim proc, które działają jako kopię swoich parametrów zabiegu.

polecam również:

  1. Jeśli nie masz zduplikowane wiersze zwracane z każdej strony UNION, a następnie zastąpić UNION z UNION ALL usunąć un potrzebne napowietrznej SQL Server sprawdzania duplikatów wartości W rzędach.What is the difference between UNION and UNION ALL?
  2. Należy unikać podpowiedzi WITH(NOLOCK), ponieważ mogą one prowadzić do problemów z spójnością danych. Podpowiedź należy stosować tylko wtedy, gdy w pełni rozumie się efekty uboczne, a aplikacja jest w porządku z brudnymi odczytami iz możliwością powrotu tego samego wiersza więcej niż raz (When should you use "with (nolock)").

Oto przykład zawierające informacje zwrotne o którym mowa powyżej:

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

Uruchom program SQL Profiler i wykonanie kodu. Sprawdź trafienie zbliża się do profilera. Skopiuj stamtąd i uruchom w oknie edytora, aby sprawdzić statystyki.

0

Użyj tego

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 
}