हाइब्रिड क्लाउड परिदृश्यों में SQL सर्वर के साथ काम करें। भाग २

एक नियम के रूप में, अनाम जानकारी सार्वजनिक क्लाउड में संग्रहीत की जाती है, और निजीकरण वाला भाग निजी में संग्रहीत किया जाता है। इस संबंध में सवाल उठता है - उपयोगकर्ता के अनुरोध पर एक परिणाम उत्पन्न करने के लिए दोनों भागों को कैसे संयोजित किया जाए? मान लीजिए कि आपके पास एक ग्राहक तालिका है जो लंबवत रूप से विभाजित है। बेनामी कॉलम Windows Azure SQL डेटाबेस में स्थित एक तालिका को सौंपा गया है, जबकि संवेदनशील जानकारी (जैसे, पूरा नाम) वाले कॉलम स्थानीय SQL सर्वर में बने हुए हैं। आपको दोनों तालिका को मुख्य CustomerID के साथ लिंक करना होगा। चूंकि वे अलग-अलग सर्वर पर अलग-अलग डेटाबेस में झूठ बोलते हैं, जॉइन के साथ एसक्यूएल स्टेटमेंट का उपयोग करना काम नहीं करता है। एक संभावित समाधान के रूप में, हमने पिछले लेख में एक परिदृश्य पर विचार किया था जिसमें स्थानीय SQL सर्वर पर बंधन हुआ था। इसने अनुप्रयोगों के लिए एक प्रकार के प्रवेश बिंदु के रूप में काम किया, और क्लाउड-आधारित SQL सर्वर एक लिंक के रूप में उस पर घाव कर रहा था। इस लेख में, हम उस मामले पर विचार करेंगे जब आवेदन के संदर्भ में स्थानीय और क्लाउड सर्वर दोनों समान हों, और डेटा को सीधे इसमें जोड़ दिया जाए, अर्थात्। व्यापार तर्क के स्तर पर।

एप्लिकेशन कोड के संदर्भ में SQL Azure से डेटा खींचना स्थानीय SQL सर्वर के साथ काम करने से अलग नहीं है। आइए इसे कनेक्शन स्ट्रिंग के लिए सटीक बताते हैं। नीचे दिए गए कोड में, u1qgtaf85k Azure SQL Server का नाम है (इसे बनाते समय यह स्वचालित रूप से उत्पन्न होता है)। आपको याद दिला दूं कि इसका कनेक्शन हमेशा TCP / IP नेटवर्क लाइब्रेरी, पोर्ट 1433 के माध्यम से स्थापित होता है। Trusted_Connection = गलत पैरामीटर इंटीग्रेटेड सिक्योरिटी नहीं है (यह SQL Azure में हमेशा मानक है), जिसका अर्थ है Trust_Server -Certificate = असत्य मैन-इन-अटैक से बचने के लिए गलत -इस-बीच।

using System; using System.Data; using System.Data.SqlClient; using System.Diagnostics; using System.Resources; namespace DevCon2013 { class Program { static void Main(string[] args) { ResourceManager resMan = new ResourceManager("DevCon2013.Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly()); string sqlAzureConnString = String.Format(@"Server=tcp:u1qgtaf85k.database.windows.net,1433;Database=AdventureWorks2012;User ID=alexejs;Password={0};Trusted_Connection=False;Encrypt=True", resMan.GetString("Password")); SqlConnection cnn = new SqlConnection(sqlAzureConnString); cnn.Open(); SqlCommand cmd = cnn.CreateCommand(); cmd.CommandText = "select top 100 CustomerID, AccountNumber from Sales.Customer order by CustomerID"; DataTable tbl = new DataTable(); tbl.Load(cmd.ExecuteReader()); cnn.Close(); foreach (DataRow r in tbl.Rows) { for (int i = 0; i < tbl.Columns.Count; i++) Debug.Write(String.Format("{0}\t", r[i])); Debug.WriteLine(""); } } } } 

लिपि १

यहां ऑन-प्रिमाइसेस संसाधन के साथ कनेक्शन जोड़ें, अर्थात स्थानीय SQL सर्वर के साथ। आपकी अनुमति से, हम मानेंगे कि इस प्रक्रिया को किसी भी स्पष्टीकरण की आवश्यकता नहीं है, इसलिए मैं सिर्फ दो तरीकों को जोड़कर पिछले कोड को संशोधित करता हूं - स्रोत से कनेक्ट करने और उस पर किसी क्वेरी को निष्पादित करने के लिए ExecuteSQL, और परिणामों के किसी भी दृश्य के लिए DumpTable। इस प्रकार, अनुप्रयोग के दृष्टिकोण से SQL Azure और ऑन-प्रिमाइसेस SQL ​​सर्वर के साथ काम करना बिल्कुल सममित रूप से होगा।

 string sqlOnPremiseConnString = @"Server=(local);Integrated Security=true;Database=AdventureWorks2012"; DataTable resultsOnPremise = ExecuteSQL(sqlOnPremiseConnString, "select BusinessEntityID, FirstName, LastName from Person.Person where BusinessEntityID between 1 and 100"); string sqlAzureConnString = String.Format(@"Server=tcp:u1qgtaf85k.database.windows.net,1433;Database=AdventureWorks2012;User ID=alexejs;Password={0};Trusted_Connection=False;Encrypt=True", resMan.GetString("Password")); DataTable resultsFromAzure = ExecuteSQL(sqlAzureConnString, "select CustomerID, AccountNumber from Sales.Customer where CustomerID between 1 and 100"); ... static DataTable ExecuteSQL(string cnnStr, string query) { SqlConnection cnn = new SqlConnection(cnnStr); cnn.Open(); SqlCommand cmd = cnn.CreateCommand(); cmd.CommandText = query; DataTable tbl = new DataTable(); tbl.Load(cmd.ExecuteReader()); cnn.Close(); return tbl; } static void DumpTable(DataTable tbl) { foreach (DataRow r in tbl.Rows) { for (int i = 0; i < tbl.Columns.Count; i++) Debug.Write(String.Format("{0}\t", r[i])); Debug.WriteLine(""); } } 

लिपि २

अब, जब हमारे पास अनुप्रयोग के अंदर दो वर्टिकल डेटाटेबल्स हैं, तो हमारे पास वर्टिकल [पहले से एकीकृत कस्टमर टेबल के दोनों टुकड़े हैं: एक स्थानीय सर्वर से, दूसरा एसक्यूएल अज़ुरे से - यह उन्हें फिर से कस्टमाइज़्ड फ़ील्ड द्वारा संयोजित करने के लिए बना रहता है, जो कि वहां मौजूद है। सादगी के लिए, हम समग्र कुंजी के मामले पर स्पर्श नहीं करेंगे, अर्थात्। हम मानते हैं कि कनेक्शन एक तालिका में एक स्तंभ से दूसरे स्तंभ में समान रूप से समीकरण द्वारा बनाया गया है। यह एक क्लासिक ADO.NET कार्य है। इसे हल करने के दो सबसे आम तरीके हैं, प्रदर्शन में लगभग बराबर। पहला तरीका DataRelation के साथ है। यह JoinTablesADO विधि में लागू किया गया है। हम एक नया डेटासेट बनाते हैं, दोनों लेबलों को इसमें जोड़ते हैं, उनके बीच एक डेटाट्रेलेशन बनाते हैं, माता-पिता में फ़ील्ड और चाइल्ड टेबल में फ़ील्ड को दर्शाते हैं, जिस पर JOIN बनाया जाएगा। दो डेटाटेबल में से कौन सी पेरेंट टेबल होगी, और कौन सी चाइल्ड टेबल है, इस स्थिति में यह मायने नहीं रखता, क्योंकि हमारे मामले में, कनेक्शन 1: कई के लिए नहीं है, लेकिन 1: 1 है। परिणामी DataTable के लिए एक रिक्त रिक्त बनाएँ। "बच्चे" तालिका के सभी रिकॉर्ड पर लूप के माध्यम से जाने पर, हमें "माता-पिता" तालिका के संबंधित रिकॉर्ड मिलते हैं और दोनों रिकॉर्ड DataRow के फ़ील्ड से गठबंधन करते हैं, जिसे हम परिणामी DataTable में डालते हैं।

 DumpTable(JoinTablesADO(resultsFromAzure, resultsOnPremise, "CustomerID", "BusinessEntityID")); ... static DataTable JoinTablesADO(DataTable parentTbl, DataTable childTbl, string parentColName, string childColName) { DataSet ds = new DataSet(); ds.Tables.Add(parentTbl); ds.Tables.Add(childTbl); DataRelation dr = new DataRelation("-", parentTbl.Columns[parentColName], childTbl.Columns[childColName]); ds.Relations.Add(dr); DataTable joinedTbl = new DataTable(); foreach (DataColumn c in parentTbl.Columns) joinedTbl.Columns.Add(c.Caption, c.DataType); foreach (DataColumn c in childTbl.Columns) joinedTbl.Columns.Add(c.Caption, c.DataType); // ., Clone()  DataColumn   :( foreach (DataRow childRow in childTbl.Rows) { DataRow parentRow = childRow.GetParentRow("-"); DataRow currentRowForResult = joinedTbl.NewRow(); for (int i = 0; i < parentTbl.Columns.Count; i++) currentRowForResult[i] = parentRow[i]; for (int i = 0; i < childTbl.Columns.Count; i++) currentRowForResult[parentTbl.Columns.Count + i] = childRow[i]; joinedTbl.Rows.Add(currentRowForResult); } return joinedTbl; } 

लिपि ३

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

 DumpTable(JoinTablesLinq(resultsFromAzure, resultsOnPremise, "CustomerID", "BusinessEntityID")); ... static DataTable JoinTablesLinq(DataTable parentTbl, DataTable childTbl, string parentColName, string childColName) { DataTable joinedTbl = parentTbl.Clone(); var childColumns = childTbl.Columns.OfType<DataColumn>().Select(c => new DataColumn(c.ColumnName, c.DataType, c.Expression, c.ColumnMapping)); joinedTbl.Columns.AddRange(childColumns.ToArray()); var joinedTblRows = from parentRow in parentTbl.AsEnumerable() join childRow in childTbl.AsEnumerable() on parentRow.Field<int>(parentColName) equals childRow.Field<int>(childColName) select parentRow.ItemArray.Concat(childRow.ItemArray).ToArray(); foreach (object[] values in joinedTblRows) joinedTbl.Rows.Add(values); return joinedTbl; } 

लिपि ४

Source: https://habr.com/ru/post/In217639/


All Articles