जिस किसी ने भी कभी ऐसे एप्लिकेशन विकसित किए हैं जो डेटाबेस का उपयोग करते हैं, उन्हें शायद एप्लिकेशन को तैनात और अपडेट करते समय डेटाबेस संरचना को अपडेट करने की समस्या का सामना करना पड़ा है।
डेटाबेस संरचना को संस्करण से संस्करण में संशोधित करने के लिए SQL स्क्रिप्ट का एक सेट बनाना सबसे आम तरीका है। बेशक, भुगतान उपकरण हैं, लेकिन वे हमेशा अद्यतन के पूर्ण स्वचालन की समस्या का समाधान नहीं करते हैं।
माइग्रेशन तकनीक, जिसे पहले हाइबरनेट ओआरएम में पेश किया गया था और लिंक में लागू किया गया था, बहुत अच्छी और सुविधाजनक है, लेकिन इसका तात्पर्य डेटाबेस संरचना विकसित करने के लिए "कोड फर्स्ट" रणनीति है, जो मौजूदा परियोजनाओं के लिए बहुत श्रमसाध्य है, और डेटाबेस में ट्रिगर, संग्रहीत कार्यविधियों और कार्यों का उपयोग "कोड पहले" रणनीति में परिवर्तन को लगभग असंभव बना देता है।
यह आलेख इस समस्या को हल करने के लिए एक वैकल्पिक दृष्टिकोण का सुझाव देता है - एक XML फ़ाइल में एक संदर्भ डेटाबेस संरचना को संग्रहीत करना और संदर्भ की तुलना के आधार पर स्वचालित रूप से एक SQL स्क्रिप्ट उत्पन्न करना मौजूदा संरचना। तो, चलिए शुरू करते हैं…
डेटाबेस संरचना के साथ XML फ़ाइल बनाना
हम DbSyncSample डेटाबेस का उपयोग करेंगे। डेटाबेस बनाने की स्क्रिप्ट नीचे दिखाई गई है।
USE [DbSyncSample] GO /****** Object: Table [dbo].[Orders] Script Date: 06/01/2017 10:37:43 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[Orders]( [Id] [int] IDENTITY(1,1) NOT NULL, [OrderNumber] [nvarchar](50) NULL, [OrderTime] [datetime] NULL, [TotalCost] [decimal](18, 2) NOT NULL, CONSTRAINT [PK_Orders] PRIMARY KEY CLUSTERED ( [Id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO CREATE NONCLUSTERED INDEX [IX_Orders_OrderNumber] ON [dbo].[Orders] ( [OrderNumber] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO /****** Object: Table [dbo].[Details] Script Date: 06/01/2017 10:37:43 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[Details]( [Id] [int] IDENTITY(1,1) NOT NULL, [Descript] [nvarchar](150) NULL, [OrderId] [int] NULL, [Cost] [decimal](18, 2) NOT NULL, CONSTRAINT [PK_Details] PRIMARY KEY CLUSTERED ( [Id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO /****** Object: Trigger [Details_Modify] Script Date: 06/01/2017 10:37:43 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TRIGGER [dbo].[Details_Modify] ON [dbo].[Details] AFTER INSERT,UPDATE AS BEGIN UPDATE Orders SET TotalCost = s.Total FROM ( SELECT i.OrderId OId, SUM(d.Cost) Total FROM Details d JOIN inserted i ON d.OrderId=i.OrderId GROUP BY i.OrderId ) s WHERE Id=s.OId END GO /****** Object: Trigger [Details_Delete] Script Date: 06/01/2017 10:37:43 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TRIGGER [dbo].[Details_Delete] ON [dbo].[Details] AFTER DELETE AS BEGIN UPDATE Orders SET TotalCost = s.Total FROM ( SELECT i.OrderId OId, SUM(d.Cost) Total FROM Details d JOIN deleted i ON d.OrderId=i.OrderId GROUP BY i.OrderId ) s WHERE Id=s.OId END GO /****** Object: Default [DF_Details_Cost] Script Date: 06/01/2017 10:37:43 ******/ ALTER TABLE [dbo].[Details] ADD CONSTRAINT [DF_Details_Cost] DEFAULT ((0)) FOR [Cost] GO /****** Object: Default [DF_Orders_TotalCost] Script Date: 06/01/2017 10:37:43 ******/ ALTER TABLE [dbo].[Orders] ADD CONSTRAINT [DF_Orders_TotalCost] DEFAULT ((0)) FOR [TotalCost] GO /****** Object: ForeignKey [FK_Details_Orders] Script Date: 06/01/2017 10:37:43 ******/ ALTER TABLE [dbo].[Details] WITH CHECK ADD CONSTRAINT [FK_Details_Orders] FOREIGN KEY([OrderId]) REFERENCES [dbo].[Orders] ([Id]) GO ALTER TABLE [dbo].[Details] CHECK CONSTRAINT [FK_Details_Orders] GO
एक कंसोल एप्लिकेशन बनाएं और शेड.DbSync nuget-package को इससे लिंक करें।
XML डेटाबेस संरचना इस प्रकार है:
class Program { private const string OrigConnString = "data source=.;initial catalog=FiocoKb;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"; static void Main(string[] args) { // getting XML with the database structure var db = new Shed.DbSync.DataBase(OrigConnString); var xml = db.GetXml(); File.WriteAllText("DbStructure.xml", xml); } }
प्रोग्राम चलाने के बाद, हम DbStructure.xml फ़ाइल में निम्नलिखित देखते हैं:
<?xml version="1.0"?> <DataBase xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Version>0</Version> <Tables> <Table Name="Orders" ObjectId="2137058649" ParentObjectId="0"> <Columns> <Column Name="Id"> <ColumnId>1</ColumnId> <Type>int</Type> <MaxLength>4</MaxLength> <IsNullable>false</IsNullable> <IsIdentity>true</IsIdentity> <IsComputed>false</IsComputed> </Column> <Column Name="OrderNumber"> <ColumnId>2</ColumnId> <Type>nvarchar</Type> <MaxLength>100</MaxLength> <IsNullable>true</IsNullable> <IsIdentity>false</IsIdentity> <IsComputed>false</IsComputed> </Column> <Column Name="OrderTime"> <ColumnId>3</ColumnId> <Type>datetime</Type> <MaxLength>8</MaxLength> <IsNullable>true</IsNullable> <IsIdentity>false</IsIdentity> <IsComputed>false</IsComputed> </Column> <Column Name="TotalCost"> <ColumnId>4</ColumnId> <Type>decimal</Type> <MaxLength>9</MaxLength> <IsNullable>false</IsNullable> <IsIdentity>false</IsIdentity> <IsComputed>false</IsComputed> </Column> </Columns> <Indexes> <Index Name="PK_Orders"> <IndexId>1</IndexId> <Type>CLUSTERED</Type> <IsUnique>true</IsUnique> <IsPrimaryKey>true</IsPrimaryKey> <IsUniqueConstraint>false</IsUniqueConstraint> <Columns> <IndexColumn> <TableColumnId>1</TableColumnId> <KeyOrdinal>1</KeyOrdinal> <IsDescendingKey>false</IsDescendingKey> </IndexColumn> </Columns> </Index> <Index Name="IX_Orders_OrderNumber"> <IndexId>2</IndexId> <Type>NONCLUSTERED</Type> <IsUnique>false</IsUnique> <IsPrimaryKey>false</IsPrimaryKey> <IsUniqueConstraint>false</IsUniqueConstraint> <Columns> <IndexColumn> <TableColumnId>2</TableColumnId> <KeyOrdinal>1</KeyOrdinal> <IsDescendingKey>false</IsDescendingKey> </IndexColumn> </Columns> </Index> </Indexes> <PrimaryKey Name="PK_Orders" ObjectId="5575058" ParentObjectId="2137058649"> <UniqueIndexId>1</UniqueIndexId> </PrimaryKey> <ForeignKeys /> <Defaults> <Default Name="DF_Orders_TotalCost" ObjectId="69575286" ParentObjectId="2137058649"> <ParentColumnId>4</ParentColumnId> <Definition>((0))</Definition> </Default> </Defaults> </Table> <Table Name="Details" ObjectId="85575343" ParentObjectId="0"> <Columns> <Column Name="Id"> <ColumnId>1</ColumnId> <Type>int</Type> <MaxLength>4</MaxLength> <IsNullable>false</IsNullable> <IsIdentity>true</IsIdentity> <IsComputed>false</IsComputed> </Column> <Column Name="Descript"> <ColumnId>2</ColumnId> <Type>nvarchar</Type> <MaxLength>300</MaxLength> <IsNullable>true</IsNullable> <IsIdentity>false</IsIdentity> <IsComputed>false</IsComputed> </Column> <Column Name="OrderId"> <ColumnId>3</ColumnId> <Type>int</Type> <MaxLength>4</MaxLength> <IsNullable>true</IsNullable> <IsIdentity>false</IsIdentity> <IsComputed>false</IsComputed> </Column> <Column Name="Cost"> <ColumnId>4</ColumnId> <Type>decimal</Type> <MaxLength>9</MaxLength> <IsNullable>false</IsNullable> <IsIdentity>false</IsIdentity> <IsComputed>false</IsComputed> </Column> </Columns> <Indexes> <Index Name="PK_Details"> <IndexId>1</IndexId> <Type>CLUSTERED</Type> <IsUnique>true</IsUnique> <IsPrimaryKey>true</IsPrimaryKey> <IsUniqueConstraint>false</IsUniqueConstraint> <Columns> <IndexColumn> <TableColumnId>1</TableColumnId> <KeyOrdinal>1</KeyOrdinal> <IsDescendingKey>false</IsDescendingKey> </IndexColumn> </Columns> </Index> </Indexes> <PrimaryKey Name="PK_Details" ObjectId="117575457" ParentObjectId="85575343"> <UniqueIndexId>1</UniqueIndexId> </PrimaryKey> <ForeignKeys> <ForeignKey Name="FK_Details_Orders" ObjectId="149575571" ParentObjectId="85575343"> <ReferenceTableId>2137058649</ReferenceTableId> <References> <Reference> <ColumnId>1</ColumnId> <ParentColumnId>3</ParentColumnId> <ReferenceColumnId>1</ReferenceColumnId> </Reference> </References> <DeleteAction>NO_ACTION</DeleteAction> <UpdateAction>NO_ACTION</UpdateAction> </ForeignKey> </ForeignKeys> <Defaults> <Default Name="DF_Details_Cost" ObjectId="101575400" ParentObjectId="85575343"> <ParentColumnId>4</ParentColumnId> <Definition>((0))</Definition> </Default> </Defaults> </Table> </Tables> <Views /> <ProgrammedObjects> <ProgObject Name="Details_Modify" ObjectId="165575628" ParentObjectId="0"> <Definition>CREATE TRIGGER [dbo].[Details_Modify] ON dbo.Details AFTER INSERT,UPDATE AS BEGIN UPDATE Orders SET TotalCost = s.Total FROM ( SELECT i.OrderId OId, SUM(d.Cost) Total FROM Details d JOIN inserted i ON d.OrderId=i.OrderId GROUP BY i.OrderId ) s WHERE Id=s.OId END</Definition> <Type>SQL_TRIGGER</Type> </ProgObject> <ProgObject Name="Details_Delete" ObjectId="181575685" ParentObjectId="0"> <Definition>CREATE TRIGGER [dbo].[Details_Delete] ON dbo.Details AFTER DELETE AS BEGIN UPDATE Orders SET TotalCost = s.Total FROM ( SELECT i.OrderId OId, SUM(d.Cost) Total FROM Details d JOIN deleted i ON d.OrderId=i.OrderId GROUP BY i.OrderId ) s WHERE Id=s.OId END</Definition> <Type>SQL_TRIGGER</Type> </ProgObject> </ProgrammedObjects> </DataBase>
XML का उपयोग करके डेटाबेस संरचना का परिनियोजन/अद्यतन
एक और खाली DbSyncSampleCopy डेटाबेस बनाएं, कंसोल प्रोग्राम कोड में निम्न कोड जोड़ें:
class Program { private const string OrigConnString = "data source=.;initial catalog=DbSyncSample;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"; private const string TargetConnString = "data source=.;initial catalog=DbSyncSampleCopy;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"; static void Main(string[] args) { // getting XML with the structure of the reference database var dborig = new Shed.DbSync.DataBase(OrigConnString); var xml = dborig.GetXml(); File.WriteAllText("DbStructure.xml", xml); // if you need to clear the structure of the target database, use // Shed.DbSync.DataBase.ClearDb(TargetConnString); // update the structure of the target database var dbcopy = Shed.DbSync.DataBase.CreateFromXml(xml); dbcopy.UpdateDb(TargetConnString); // in fact, you can use one line: // dborig.UpdateDb(TargetConnString); // create dbcopy only to demonstrate the creation of a database object from XML } }
प्रोग्राम चलाने के बाद, आप सत्यापित कर सकते हैं कि DbSyncSampleCopy में अब संदर्भ डेटाबेस के समान तालिका संरचना है। बेझिझक संदर्भ संरचना को बदलने और लक्ष्य को अपडेट करने के साथ प्रयोग करें।
परीक्षण परिदृश्यों में, आपको शुरुआत से हर बार एक परीक्षण डेटाबेस बनाने की आवश्यकता हो सकती है। इस मामले में, Shed.DbSync.DataBase.ClearDb(string connString) फ़ंक्शन का उपयोग करना उपयोगी होगा।
स्वचालित डेटाबेस संरचना ट्रैकिंग
संरचना ट्रैकिंग को एक अलग फ़ंक्शन बनाया गया है, जिसे एप्लिकेशन के प्रारंभ/पुनः प्रारंभ होने पर, या किसी अन्य स्थान पर डेवलपर के अनुरोध पर कॉल किया जाना चाहिए।पी>
static void SyncDb() { // autotracking of database structure Shed.DbSync.DataBase.Syncronize(OrigConnString, @"Struct\DbStructure.xml", // path to the structure file @"Struct\Logs", // path to synchronization log folder @"Struct\update_script.sql" // (optional) in case of defining this parameter // the script generated for the database update // will be stored within it ); }SCRIPT
XML में संस्करण पैरामीटर (टैग) का उपयोग करके ट्रैकिंग की जाती है। प्रक्रिया का उपयोग करने का परिदृश्य इस प्रकार है:
डेटाबेस के लिए एक संस्करण असाइन करें। Microsoft SQL सर्वर प्रबंधन स्टूडियो में, आवश्यक डेटाबेस के नोड पर राइट-क्लिक करें और गुण चुनें।
अगला, विस्तारित गुण क्लिक करें और गुण तालिका में मान 1 के साथ संस्करण गुण जोड़ें। संरचना के प्रत्येक बाद के संशोधन के साथ, इस संपत्ति को 1 से बढ़ाया जाना चाहिए।
जब आप एप्लिकेशन शुरू करते हैं, तो फ़ाइल बनाई जाएगी, यदि कोई XML फ़ाइल नहीं है या इसका संस्करण डेटाबेस से छोटा है।
यदि XML फ़ाइल का संस्करण डेटाबेस से बड़ा है, तो डेटाबेस को अद्यतन करने के लिए एक स्क्रिप्ट तैयार की जाती है और निष्पादित की जाती है।
यदि स्क्रिप्ट के निष्पादन के दौरान त्रुटियां होती हैं, तो सभी परिवर्तन वापस ले लिए जाते हैं।
सिंक्रनाइज़ेशन परिणाम logDitPath पैरामीटर द्वारा निर्दिष्ट फ़ोल्डर में बनाई गई लॉग फ़ाइल में लिखे जाते हैं।
यदि SqlScriptPath पैरामीटर निर्दिष्ट है, तो आइटम 4 की स्क्रिप्ट वाली एक फ़ाइल बनाई जाती है।