दिलचस्प पोस्ट
कैसे डेटाबेस में समवर्ती अद्यतन से निपटने के लिए? मैं एक। MySqlCommand में एक MySQL उपयोगकर्ता परिभाषित चर का उपयोग कैसे कर सकता हूँ? सी # में डिफ़ॉल्ट नेमस्पेस के साथ Xpath का उपयोग करना स्विंग जीयूआई में मान्य (), पुन: संशोधित () और अमान्य () के बीच का अंतर क्या एक .net MySqlCommand में एक MySQL उपयोगकर्ता परिभाषित चर का उपयोग करना संभव है? प्रदाता ओरेकल क्लाइंट के संस्करण के साथ संगत नहीं है डेल्फी का उपयोग करके एचटीटीपी जीईटी यूआरएल को कॉल करने का सबसे आसान तरीका क्या है? पैकेज के पुराने संस्करण को डाउनलोड करें सरणी () और के बीच PHP अंतर डिफ़ॉल्ट ऑब्जेक्ट.स्टोस्टिंग () क्यों हैशोड में शामिल है? कैसे एक Redux अनुप्रयोग में कोड बंटवारे के लिए reducers गतिशील लोड करने के लिए? एक regex में वर्ग कोष्ठक और कोष्ठक के बीच अंतर क्या है? HTML5 – एमपी 4 वीडियो IE9 में नहीं खेलता है स्विफ्ट-भाषा में त्रुटि-हैंडलिंग वीएस2013 में डिबगिंग करते समय प्रमाणीकरण समस्या – आईआईएस एक्सप्रेस

पास शब्दकोश <string, int> को संग्रहित प्रक्रिया T-SQL

मेरे पास एमवीसी आवेदन है कार्रवाई में मुझे Dictionary<string,int> Key आईडी है और Value सॉर्टऑर्डर नंबर है मैं संग्रहीत कार्यप्रणाली बनाना orderNumber जो कि कुंजी (आईडी) को इस रिकॉर्ड को डेटाबेस में orderNumber और orderNumber कॉलम को डिक्शनरी से value से बचा orderNumber मैं डेटा को अद्यतन करने के लिए कई बार कॉल करने के बजाय, एक बार एक बार संग्रहीत कार्यविधि को कॉल करना और उसके पास डेटा पास करना चाहता हूं।

क्या आपको कोई विचार है? धन्यवाद!

वेब के समाधान से एकत्रित समाधान "पास शब्दकोश <string, int> को संग्रहित प्रक्रिया T-SQL"

तालिका मानद मानदंडों का उपयोग करना वास्तव में जटिल नहीं है

यह एसक्यूएल दिया:

 CREATE TYPE MyTableType as TABLE (ID nvarchar(25),OrderNumber int) CREATE PROCEDURE MyTableProc (@myTable MyTableType READONLY) AS BEGIN SELECT * from @myTable END 

यह दिखाएगा कि यह कितना अपेक्षाकृत आसान है, यह केवल उन मानों का चयन करता है जिन्हें आपने डेमो प्रयोजनों के लिए भेजा था। मुझे यकीन है कि आप आसानी से अपने मामले में यह दूर कर सकते हैं।

 using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; namespace TVPSample { class Program { static void Main(string[] args) { //setup some data var dict = new Dictionary<string, int>(); for (int x = 0; x < 10; x++) { dict.Add(x.ToString(),x+100); } //convert to DataTable var dt = ConvertToDataTable(dict); using (SqlConnection conn = new SqlConnection("[Your Connection String here]")) { conn.Open(); using (SqlCommand comm = new SqlCommand("MyTableProc",conn)) { comm.CommandType=CommandType.StoredProcedure; var param = comm.Parameters.AddWithValue("myTable", dt); //this is the most important part: param.SqlDbType = SqlDbType.Structured; var reader = comm.ExecuteReader(); //or NonQuery, etc. while (reader.Read()) { Console.WriteLine("{0} {1}", reader["ID"], reader["OrderNumber"]); } } } } //I am sure there is a more elegant way of doing this. private static DataTable ConvertToDataTable(Dictionary<string, int> dict) { var dt = new DataTable(); dt.Columns.Add("ID",typeof(string)); dt.Columns.Add("OrderNumber", typeof(Int32)); foreach (var pair in dict) { var row = dt.NewRow(); row["ID"] = pair.Key; row["OrderNumber"] = pair.Value; dt.Rows.Add(row); } return dt; } } } 

का उत्पादन

 0 100 1 101 2 102 3 103 4 104 5 105 6 106 7 107 8 108 9 109 

एक टीवीप का उपयोग करने का स्वीकार्य जवाब आम तौर पर सही है, लेकिन कुछ स्पष्टीकरण की आवश्यकता होती है, जिसमें डेटा की मात्रा के आधार पर पारित किया जाता है। डेटाटाले का उपयोग करना डेटा के छोटे सेटों के लिए ठीक है (त्वरित और आसान नहीं कहना है), लेकिन बड़े सेटों के लिए स्केल नहीं दिया गया है कि यह डाटासेट में इसे केवल SQL सर्वर के पास करने के साधन के लिए डेटासेट में डुप्लिकेट करता है। इसलिए, डेटा के बड़े सेटों के लिए किसी भी कस्टम संग्रह की सामग्री को स्ट्रीम करने का विकल्प होता है। एकमात्र वास्तविक आवश्यकता यह है कि आपको एसक्यूएलडीबी प्रकार के संदर्भ में ढांचे को परिभाषित करने की जरूरत है और संग्रह के माध्यम से पुनरावृत्त करना है, जो दोनों काफी तुच्छ कदम हैं।

न्यूनतम संरचना का एक सरलीकृत अवलोकन नीचे दिखाया गया है, जो कि मैंने जिस उत्तर पर पोस्ट किया है उसका अनुकूलन मैं संभवतः कम से कम 10 मिलियन रिकॉर्ड कैसे जोड़ सकता हूं? , जो एक फ़ाइल से डेटा आयात करने के साथ काम करता है और इसलिए थोड़ा अलग है क्योंकि डेटा वर्तमान में स्मृति में नहीं है जैसा कि आप नीचे दिए गए कोड से देख सकते हैं, यह सेटअप अभी तक अत्यधिक लचीला और साथ ही कुशल और स्केलेबल नहीं है।

SQL वस्तु # 1: संरचना को परिभाषित करें

 -- First: You need a User-Defined Table Type CREATE TYPE dbo.IDsAndOrderNumbers AS TABLE ( ID NVARCHAR(4000) NOT NULL, SortOrderNumber INT NOT NULL ); GO 

SQL वस्तु # 2: संरचना का उपयोग करें

 -- Second: Use the UDTT as an input param to an import proc. -- Hence "Tabled-Valued Parameter" (TVP) CREATE PROCEDURE dbo.ImportData ( @ImportTable dbo.IDsAndOrderNumbers READONLY ) AS SET NOCOUNT ON; -- maybe clear out the table first? TRUNCATE TABLE SchemaName.TableName; INSERT INTO SchemaName.TableName (ID, SortOrderNumber) SELECT tmp.ID, tmp.SortOrderNumber FROM @ImportTable tmp; -- OR -- some other T-SQL -- optional return data SELECT @NumUpdates AS [RowsUpdated], @NumInserts AS [RowsInserted]; GO 

सी # कोड, भाग 1: इटरेटर / प्रेषक को परिभाषित करें

 using System.Collections; using System.Data; using System.Data.SqlClient; using System.IO; using Microsoft.SqlServer.Server; private static IEnumerable<SqlDataRecord> SendRows(Dictionary<string,int> RowData) { SqlMetaData[] _TvpSchema = new SqlMetaData[] { new SqlMetaData("ID", SqlDbType.NVarChar, 4000), new SqlMetaData("SortOrderNumber", SqlDbType.Int) }; SqlDataRecord _DataRecord = new SqlDataRecord(_TvpSchema); StreamReader _FileReader = null; // read a row, send a row foreach (KeyValuePair<string,int> _CurrentRow in RowData) { // You shouldn't need to call "_DataRecord = new SqlDataRecord" as // SQL Server already received the row when "yield return" was called. // Unlike BCP and BULK INSERT, you have the option here to create an // object, do manipulation(s) / validation(s) on the object, then pass // the object to the DB or discard via "continue" if invalid. _DataRecord.SetString(0, _CurrentRow.ID); _DataRecord.SetInt32(1, _CurrentRow.sortOrderNumber); yield return _DataRecord; } } 

सी # कोड, भाग 2: इटरेटर / प्रेषक का उपयोग करें

 public static void LoadData(Dictionary<string,int> MyCollection) { SqlConnection _Connection = new SqlConnection("{connection string}"); SqlCommand _Command = new SqlCommand("ImportData", _Connection); SqlDataReader _Reader = null; // only needed if getting data back from proc call SqlParameter _TVParam = new SqlParameter(); _TVParam.ParameterName = "@ImportTable"; // _TVParam.TypeName = "IDsAndOrderNumbers"; //optional for CommandType.StoredProcedure _TVParam.SqlDbType = SqlDbType.Structured; _TVParam.Value = SendRows(MyCollection); // method return value is streamed data _Command.Parameters.Add(_TVParam); _Command.CommandType = CommandType.StoredProcedure; try { _Connection.Open(); // Either send the data and move on with life: _Command.ExecuteNonQuery(); // OR, to get data back from a SELECT or OUTPUT clause: SqlDataReader _Reader = _Command.ExecuteReader(); { Do something with _Reader: If using INSERT or MERGE in the Stored Proc, use an OUTPUT clause to return INSERTED.[RowNum], INSERTED.[ID] (where [RowNum] is an IDENTITY), then fill a new Dictionary<string, int>(ID, RowNumber) from _Reader.GetString(0) and _Reader.GetInt32(1). Return that instead of void. } } finally { _Reader.Dispose(); // optional; needed if getting data back from proc call _Command.Dispose(); _Connection.Dispose(); } } 

संगृहीत प्रक्रियाएं सरणियों के रूप में इनपुट का समर्थन नहीं करती हैं। Googling एक्सएमएल या अल्पविराम से अलग तारों का उपयोग करके कुछ हैक्स प्रदान करता है, लेकिन ये हैक्स हैं

ऐसा करने के लिए एक अचूक तरीके से एक अस्थायी तालिका (उदा। नाम #Orders ) बनाने और #Orders सभी डेटा डालें। फिर आप एक ही खुला एसक्यूएल कनेक्शन का इस्तेमाल करके एसपी को कॉल कर सकते हैं और सपा को मूल्यों को पढ़ने के लिए #Orders टेबल का इस्तेमाल कर सकते हैं।

एक अन्य समाधान तालिका-मान वाले पैरामीटर का उपयोग करना है, लेकिन इसमें सेटअप के लिए कुछ और एसक्यूएल की आवश्यकता है, इसलिए मुझे लगता है कि टेम्पप तालिका दृष्टिकोण का उपयोग करना शायद आसान है