2012-04-19 19 views
10

मैं डेटाबेस अद्यतन करने के लिए xml फ़ाइलों को पढ़ने के लिए कोडिंग कर रहा हूं। मुझे लगभग 500 एक्सएमएल फाइलें मिलती हैं और मैं उन्हें जितनी जल्दी कर सकता हूं उन्हें संसाधित करना चाहता हूं।क्या एक ही ऑपरेशन में कई संग्रहीत प्रक्रियाओं को निष्पादित करना संभव है?

सभी डेटाबेस संचालन संग्रहीत प्रक्रियाओं का उपयोग करके किया जाता है।

प्रत्येक XML फ़ाइल के लिए लगभग 35 अलग-अलग संग्रहित प्रक्रियाएं हैं।

शुरू में मैं इस

var cmd = new SqlCommand("EXEC UpdateTeamStats("+teamId+","+points+")"); 
cmd.CommandType = CommandType.Text; 

की तरह कोड लिखा था लेकिन कुछ सर्वोत्तम प्रथाओं के माध्यम से जाने के बाद मैं इसे

var cmd = new SqlCommand("UpdateTeamStats"); 
cmd.CommandType = CommandType.StoredProcedure; 
cmd.Parameters.Add("teamId", 21); 
cmd.Parameters.Add("points", 2); 
संग्रहित प्रक्रियाओं की उच्च संख्या की वजह से

करने के लिए बदल कार्यक्रम से बुलाया जा रहा है मुझे एहसास हुआ कि अनुकूलित करने के लिए मुझे कम संख्या में कॉल करना है।

इसलिए मैं सभी 35 संग्रहीत प्रक्रियाओं को एक साथ इकट्ठा करना चाहता हूं और उन्हें एक ही बार में निष्पादित करना चाहता हूं।

संग्रहित प्रक्रियाएं अलग-अलग मानकों के साथ अलग हैं और मुझे ऊपर दिए गए पैरामीटर परिवर्तनों के बाद उन्हें एकत्रित करने और निष्पादित करने का कोई तरीका नहीं पता है।

मैं एक विशाल संग्रहित प्रक्रिया को कॉल करने और अन्य 35 को कॉल करने वाली संग्रहीत प्रक्रिया के अंदर सोच रहा था, लेकिन मैं एसक्यूएल में बहुत अच्छा नहीं हूं और इससे अनावश्यक जटिलता होगी।

क्या यह पूरी तरह से सी # में ऐसा करना संभव है?

या वहां storedprocedures अप कतार और उन्हें तेजी से चलाने के

+0

तुम क्या करते होने की उम्मीद है जब आपके निष्पादन के बीच में, एक त्रुटि हुई है? क्या सभी निष्पादित प्रक्रिया रोलबैक होगी? या बस शेष प्रक्रियाओं को संसाधित करना जारी रखें? –

+0

ध्यान दें कि आपका शीर्षक "समानांतर में" कहता है लेकिन आपका प्रश्न पढ़ रहा है, ऐसा लगता है कि आप बस "एक डेटाबेस कमांड के रूप में" –

+0

@ जॉर्ज डकेट - यह मेरा संपादन था। मूल "एक बार में" था। – Oded

उत्तर

0

आप एक CommandQueue बना सकते हैं करने के लिए कुछ अन्य बेहतर तरीका है, Command pattern के माध्यम से और आदेश है कि जो कुछ अपनी आवश्यकताओं के कॉल के लिए कर रहे हैं करने के लिए नक्शे पर एक प्रतिनिधि बनाने संग्रहीत प्रक्रिया के लिए; दिखता द्वारा, कुछ की तरह:

public class CommandQueue 
{ 
    private Connection _connexion = new Connection(); // Set this up somehow. 

    // Other methods to handle the concurrency/ calling/ transaction etc. 

    public Func<string, Dictionary<string, int>, bool> CallStoredProcedure = (procedureName, parameterValueMap) => 
    { 
     cmd.Connection = GetConnexion(); 
     var cmd = new SqlCommand(procedureName); 
     cmd.CommandType = CommandType.StoredProcedure; 

     foreach (var parameterValueMapping in parameterValueMap) 
     { 
     cmd.Parameters.Add(parameterValueMapping.Key, parameterValueMapping.Value); 
     } 

     var success = cmd.ExecuteNonQuery(); 

     return success; 
    } 

    private Connection GetConnexion() 
    { 
     return _connexion; 
    } 
} 

और फिर, सेटअप CommandQueue है, तो आप धागे का एक पूल, जिसमें से आप एक नया धागा पर प्रतिनिधि कॉल कर सकते हैं, ताकि वे समानांतर में चलाने है।

वास्तव में, SQLCommand कक्षा को देखते हुए, आप इस पर असीमित कॉल कर सकते हैं। इसलिए, आप अपनी प्रत्येक संग्रहीत प्रक्रियाओं को असीमित रूप से कॉल करने में सक्षम होना चाहिए, प्रत्येक प्रतिनिधि को पूरा करने और इसे सभी को लपेटने के लिए एक प्रतिनिधि सेट अप करें, ताकि प्रत्येक आदेश पर Cancel() पर कॉल करके आपको उन्हें वापस रोल कर सकें। मैं शायद इसे अभी भी CommandQueue का उपयोग करने के लिए उपयोग करने के लिए उपयोग करता हूं, जैसा कि मैं सुझाव दूंगा कि आप इसे बाद में बदल देंगे!

मुझे लगता है कि मैं अभी भी CommandQueue पर एक प्रतिनिधि के साथ संग्रहीत प्रक्रिया-कॉलिंग को समाहित कर दूंगा, ताकि यह संग्रहीत प्रो के विवरण को बाहर कर सके और प्रक्रिया को किसी और के लिए समझने में आसान हो और इसे बनाए रखना भी आसान हो। यदि आप नई संग्रहित प्रोसेस जोड़ते हैं, या नाम बदलते हैं, या कुछ बदलना बहुत आसान होगा। आप एक स्थिर सूची सेट कर सकते हैं सभी प्रतिनिधियों, या आवश्यक संग्रहित प्रक्रिया विवरण के साथ एक स्थिर सूची और केवल पैरामीटर में पास करने के लिए प्रतिनिधि का उपयोग कर सकते हैं।

1

http://www.microsoft.com/download/en/details.aspx?id=435

ठीक से Microsoft अनुप्रयोग डेटा ब्लॉक डाउनलोड, लेकिन मैं इसका उपयोग कैसे करूं कृपया?

इस रैपर वर्ग का उपयोग काफी सरल है।

DAC DC = new DAC(); 
DC.StoredProcedure = "nProc_InsertOrder"; 
DC.Params.Add("@OrderId", SqlDbType.VarChar, "Order1"); 
DC.Params.Add("@CustomerName", SqlDbType.VarChar, "test"); 
DAC.Commands.Add(DC); 

DC = new DAC(); 
DC.StoredProcedure = "nProc_InsertOrderLineItems"; 
DC.Params.Add("@OrderId", SqlDbType.VarChar, "Order1"); 
DC.Params.Add("@OrderLineId", SqlDbType.VarChar, "A1"); 
DAC.Commands.Add(DC); 

DC = new DAC(); 
DC.StoredProcedure = "nProc_InsertOrderLineItems"; 
DC.Params.Add("@OrderId", SqlDbType.VarChar, "Order1"); 
DC.Params.Add("@OrderLineId", SqlDbType.VarChar, "A2"); 
DAC.Commands.Add(DC); 

DC = new DAC(); 
DC.StoredProcedure = "nProc_CreateBill"; 
DC.Params.Add("@BillDate", SqlDbType.DateTime, DateTime.Now); 
DC.Params.Add("@BillId", SqlDbType.VarChar, "Bill1"); 
DAC.Commands.Add(DC); 
DAC.ExecuteBatch(); 

यदि आदेश सम्मिलन विफल हो गया है, तो बिल नहीं बनाया जाना चाहिए। इसी तरह, यदि लाइन आइटम विफल हो जाते हैं, तो ऑर्डर नहीं बनाया जाना चाहिए। हम इसे ADO.Net के माध्यम से कोड की कुछ पंक्तियों में प्राप्त कर रहे हैं।

इस उदाहरण में, जब तक हम ExecuteBatch को कॉल नहीं करते हैं, हम वास्तव में रिकॉर्ड नहीं डाल रहे हैं लेकिन बैच अपडेट बनाने के लिए ऑब्जेक्ट तैयार कर रहे हैं।

+0

मुख्य डीएसी ऑब्जेक्ट कहां से आता है - जिसे हम 'DAC.Commands.Add' के लिए उपयोग कर रहे हैं? यह स्थैतिक नहीं हो सकता है यह धागा-सुरक्षित नहीं होगा! और क्या यह वास्तव में करता है जो हम यहां चाहते हैं - SQL सर्वर क्लाइंट क्लास से स्पष्ट समर्थन के बिना यह वास्तव में केवल एक डीबी राउंड-ट्रिप करता है या इसके बजाय सभी आदेशों को लेनदेन में लपेटता है? – Rup

+0

हम सभी आदेशों को एक ही ऑब्जेक्ट में लपेट रहे हैं और उन्हें लेनदेन के साथ एक खुले कनेक्शन में निष्पादित कर रहे हैं। –

1

सबसे अच्छा समाधान आईएमओ एक तालिका-मूल्यवान पैरामीटर के साथ एक एकल संग्रहित प्रक्रिया लिखना होगा जिसमें प्रति xml फ़ाइल के सभी पैरामीटर की एक सूची होगी। फिर इस संग्रहित प्रो में तालिका-मूल्यवान पैरामीटर में प्रत्येक रिकॉर्ड के लिए सभी अन्य संग्रहीत प्रोसेस को कॉल करें।

यदि यह ठीक नहीं है, तो आप संग्रहित प्रक्रिया के बजाय प्रकार के टेक्स्ट का एक SQLCommand का उपयोग कर सकते हैं और जब आप जाते हैं और इसे निष्पादित करते हैं तो बस कमांड का निर्माण कर सकते हैं। आप पैरामीटर का उपयोग कर सकते हैं जैसा कि आप अभी करते हैं या आप केवल गतिशील एसक्यूएल लिख सकते हैं।

0

व्यक्तिगत रूप से, और मेरे अनुभव ADO.NET का उपयोग करने में, मुझे लगता है कि आप अलग एक एकलSqlConnection का उपयोग कर बयान के रूप में इन क्रियान्वित कोई मुद्दा होगा।

यह .NET के अद्भुत connection pooling का लाभ उठाने का लाभ है, जो आपको व्यक्तिगत रूप से प्रत्येक आदेश के साथ काम/अनुकूलित/बातचीत करने में सक्षम बनाता है और एक साझा कनेक्शन सवारी करता है (कनेक्शन को ब्रोकरिंग की मात्रा को कम करने के लिए)।

मैं यहां using खंडों के महत्वपूर्ण पर जोर देना चाहूंगा जो विभिन्न संसाधनों के उचित निपटान की सुविधा प्रदान करते हैं।

उदाहरण के लिए:

using (var conn = new SqlConnection("connection string")) 
{ 
    using (var cmd = new SqlCommand()) 
    { 
     cmd.Connection = conn; 
     cmd.CommandType = CommandType.StoredProcedure; 

     //ready to query 
     conn.Open(); 

     cmd.CommandText = "UpdateTeamStats"; 
     var teamIdParam = new SqlParameter("teamId", 21); 
     var pointsParam = new SqlParameter("points", 2); 

     cmd.Parameters.Add(teamIdParam); 
     cmd.Parameters.Add(pointsParam); 

     cmd.ExecuteNonQuery(); //OR if you're async cmd.ExecuteNonQueryAsync(); 

     //the rest of your executions 

     conn.Close(); 
    } 
} 

और अगर मैं एक पल के लिए लालायित रहा हूँ, आप एक पुस्तकालय, मेरा DbConnect की तरह है, जो करने के लिए ऊपर कम कर देता है का उपयोग कर सकते हैं:

using (var db = new DbConnect("connection string")) 
{ 
    db.SetSqlCommand("UpdateTeamStats"); 
    db.AddParameter("teamId", 21); 
    db.AddParameter("points", 2); 

    db.ExecuteNonQuery().Wait(); //OR if youre async await db.ExecuteNonQuery(); 

    db.ClearParameters(); 
    db.SetSqlCommand("some other proc"); 

    //rest of executions 
} 
संबंधित मुद्दे

 संबंधित मुद्दे