Concurrency Understanding

कई बार ऐसी स्थिति होती है, जब हम किसी Conflict को घटित होने से किसी भी स्थिति में नहीं रोक सकते। उदाहरण के लिए यदि एक ही समय पर एक User जिस Row को Update कर रहा होता है, ठीक उसी समय उसी Record को कोई अन्य User भी Modify कर रहा हो सकता है। इस स्थिति में एक ही Record दो अलग Users के माध्‍यम से Change होने की स्थिति में निश्चित रूप से Conflict की स्थिति पैदा होती है। इस प्रकार के Conflict से बचने के लिए हम दो तरीके उपयोग में ले सकते हैं, जो कि अग्रानुसार हैं:

Pessimistic Concurrency

समान समय पर एक से ज्यादा Users समान Row को Update न कर सकें, इसके लिए सबसे बेहतर तरीका ये है कि जो User किसी Row को Update कर रहा है, उस Row को कोई भी दूसरा User तब तक Access न कर सके, जब तक कि पहला User उस Row को पूरी तरह से Update करते हुए अपनी जरूरत को पूरा न कर ले।

इस प्रकार की स्थिति में जो User Row को पहले Access करता है, वह Row उस User के लिए तब तक के लिए Lock हो जाता है, जब तक कि वह User अपना काम पूरा नहीं कर लेता। इस स्थिति में यदि कोई दूसरा User उस Locked Row को Access करने की कोशिश करता है, तो Database उसे ऐसा करने से रोकता है।

लेकिन इस तरीके का भी अपना Drawback है। क्योंकि यदि हम इस तरीके को Use करते हैं, तो Underlying Database के साथ तब तक Connection Open रखना जरूरी होता है, जब तक कि पहला User अपना काम पूरा नहीं कर लेता, जो कि ADO.NET के Disconnected Architecture के Rule के विपरीत है, जिसके अनुसार Underlying Database से जितना देर से सम्भव हो, उतना देर से Connection स्थापित करना चाहिए और जितना जल्दी सम्भव हो, उतना जल्दी Connection Close कर देना चाहिए।

इतना ही नहीं, Row Locking तकनीक का प्रयोग करने का एक नुकसान और होता है जिसके अन्तर्गत Row Locking करने पर Underlying Database को न केवल Row को अन्य User द्वारा Access होने से रोकने के लिए Protect करना होता है, बल्कि बार-बार इस बात को भी Check करना होता है, कि पहले User ने Row को Unlock किया या नहीं, ताकि उसे अन्य User द्वारा Access करने हेतु Available किया जा सके।

Row Lock करने की एक और परेशानी ये है कि Row Locking के कारण Connection Pooling को पूरी तरह से उपयोग में लिया जाना सम्भव नहीं हो पाता, जिसकी वजह से Connection को लम्बे समय तक Open रखना पडता है। परिणामस्वरूप Underlying Database की Performance प्रभावित होती है। इसी Performance को Improve करने के लिए ADO.NET हमें Disconnected Architecture Provide करता है।

लेकिन Disconnected Architecture को Use करने पर Key-Conflicting जैसी समस्या पैदा होती है। हालांकि इस समस्या को Solve करने के लिए हमें उस स्थिति में अलग से कुछ करने की जरूरत नहीं होती, जबकि हम ADO.Net को Use करते हैं, क्योंकि ADO.NET इसे स्वयं ही अपने स्तर पर Handle कर लेता है।

जब हम ADO.NET Use करते हैं, तो Key Related समस्या को तो ADO.NET द्वारा Handle कर लिया जाता है, लेकिन समस्या तब पैदा होती है, जब हम ऐसा Connection Create करते हैं, जो किसी Row को Lock करता है और वह Lock स्वयं फिर से किसी अन्य Row को Lock कर देता है। इस प्रकार की स्थिति में कई बार Deadlock की स्थिति बन जाती है, जो कि एक बहुत ही खराब स्थिति होती है क्योंकि इस स्थिति में हर Concurrent Connection को DBA को Manually Close करना पडता है।

इसलिए इस प्रकार की स्थिति से बचने के लिए Timeout तरीके को Use किया जाता है, जिसके अन्तर्गत एक निश्चित समय तक किसी Resource पर Deadlock जैसी स्थिति होने पर Database स्वयं ही Appropriate Action लेते हुए Deadlock की स्थिति को समाप्त कर देता है। Row Locking के इस तरीके को Use करते हुए Concurrency को Handle करने की व्‍यवस्था को Pessimistic Concurrency के नाम से जाना जाता है और सामान्यत: इस Concurrency को केवल उस स्थिति में ही उपयोग में लिया जाता है, जबकि हमारे पास कोई अन्य तरीका नहीं होता।

Optimistic Concurrency

इस Concurrency में ये माना जाता है कि Data को Corrupt होने से बचाने के लिए उसे Lock करना जरूरी नहीं है। बल्कि हम कई ऐसे तरीके Use कर सकते हैं, जिनके माध्‍यम से Data को INSERT, UPDATE या DELETE करने से पहले ही Validity के लिए Check कर लिया जाता है।

परिणामस्वरूप Insert, Update या Delete Operation Perform होने से पहले ही इस बात को Check कर लिया जाता है कि Update किए जाने वाले Row का Data किसी अन्य User द्वारा पहले ही Change किया जा चुका है या नहीं।

हालांकि ये तरीका Use करने पर यदि किसी अन्य User द्वारा Data को पहले ही Change किया जा चुका हो, तो Insert, Update या Delete Operation Fail हो जाता है, लेकिन फिर भी ये तरीका Pessimistic Locking की तुलना में ज्यादा बेहतर तरीका है। Optimistic Concurrency को Manage करने के लिए हम जिन तरीकों को Use कर सकते हैं, वे निम्नानुसार हैं:

Last-In is Final

इस तरीके के अन्तर्गत जो Data सबसे अन्त में Update होता है, Database उस Data को याद रखता है। ये तरीका सबसे सरल Optimistic Concurrency Scheme को Represent करता है और हमें इस तरीके को Use करते समय कुछ भी Extra करने की जरूरत नहीं होती है क्योंकि इस तरीके के अन्तर्गत जो Record सबसे बाद में Insert या Update होता है, वही Record Database में Final Record की तरह Saved रहता है।

Check All Columns before Update

इस तरीके के अन्तर्गत हम Data को Underlying Database में Permanently Update करने से पहले उस Row के साथ WHERE Clause के माध्‍यम से एक Condition Apply करते हैं। परिणामस्वरूप यदि Condition Match होती है, तो ही Underlying Database का Data Change होता है।

इस WHERE Clause में हम Underlying Database के जिस Row को Update कर रहे होते हैं, उस Row के सभी Columns के Data को पिछले Data से Compare करते हैं और यदि कोई भी Data Modified हो चुका होता है, तो हमारे द्वारा Modified Data Underlying Database में Save नहीं होता। बल्कि Database अन्य Users द्वारा Modify किए गए Updated Data से हमारे DataSet Object को Fill कर देता है।

परिणामस्वरूप यदि हम चाहें तो अपने Changes को फिर से Save करने के लिए DataAdapter के Update() Method को Use कर सकते हैं। इस तरीके को ADO.NET तब Use करता है, जब हम Drag-and-Drop तकनीक का प्रयोग करते हुए Database Application Design करते हैं।

Check Only Modified Columns and Primary Key

ये तरीका पिछले तरीके की तरह ही काम करता है। अन्तर केवल इतना है कि पिछले तरीके में हम हर Column के Data को Update करने से पहले उसमें Stored पिछली Value से Compare करते हैं, जिससे Database की Performance प्रभावित होती है, जबकि इस तरीके से हम केवल Modify किए जाने वाले Columns व Primary Key Column को ही अन्य User द्वारा Perform किए गए Modification के लिए Check करते हैं, जिससे Database की Performance पर तुलनात्मक रूप से कम Negative Effect पडता है।

Checking Timestamps

सामान्यत: हम हर Table में एक Timestamp Column रखते हैं, जिसके समय को हर Modification के साथ Current Time से Set कर दिया जाता है। परिणामस्वरूप यदि इस Column व Primary Key के मान को ही Compare करके इस बात का पता लगा लिया जाता है कि जिस Row को Modify किया जा रहा है, उसे किसी अन्य User द्वारा Modify किया गया है या नहीं।

यदि किसी अन्य User द्वारा उस Row को Modify किया गया होगा, तो Timestamp Column का मान हमारे DataSet Object के Row के Timestamp के मान से भिन्न होगा। उस स्थिति में हम पिछले तरीके को इस तरीके के साथ Mix करते हुए अपने Row को ज्यादा बेहतर Performance के साथ Update कर सकते हैं।

Concurrency Implementing

पिछले Section में Discuss किए अनुसार हम हमारी जरूरत के आधार पर दोनों में से किसी भी Concurrency Management तरीके को Use कर सकते हैं। Concurrency Mechanism का Selection करने के बाद भी हमें कुछ और Issues पर ध्‍यान देना जरूरी होता है, ताकि हम Concurrency को बेहतर तरीके से Control कर सकें। Concurrency Related अन्य Issues, जिन्हें ध्‍यान देने की जरूरत होती है, निम्नानुसार हैं:

Handling Null Values for DataSet

Database Software या C++ जैसी Programming Languages में Nullable Values को Represent करने की सुविधा होती है, लेकिन .NET Framework में Null Value को इन Programming Languages की तरह Treat नहीं किया जा सकता। इसलिए .NET 2.0 में Nullable Value Type के लिए एक नया Option Provide किया गया है, जिसका प्रयोग करके हम हमारे Disconnected DataSet Object में किसी Column को Nullable यानी Null Value से Fill कर सकते हैं।

Database के null को .NET में System.DBNull Structure द्वारा Represent किया जाता है। सामान्यत: हम इसे System.Convert.DBNull Constant के माध्‍यम से आसानी से Retrieve कर सकते हैं और किसी Column में NULL Value के रूप में Assign कर सकते हैं।

जबकि Null Value को Read करते समय हम DbDataReader.IsNull() Method को Use कर सकते हैं, जो True/False के रूप में इस बात का Indication देता है कि किसी Column में null Value Exist है या नहीं। इसके अलावा जरूरत के आधार पर हम GetValue() के Result को DataReader के Loop में DBNull.Value के माध्‍यम से भी Compare कर सकते हैं।

Strongly Typed DataSet Object Null Value को Set करने की इस व्‍यवस्था को और आसान बना देता है, जहां हम निम्नानुसार Statement का प्रयोग करते हुए DataSet के Columns में Null Values को Set कर सकते हैं:

dr.IsLNameNull();                   //Getting Value
dr.SetLNameNull();                //Setting Value

जबकि यदि ये Strongly Typed DataSet Object नहीं होता, तो हमारा Code कुछ निम्नानुसार होता-

if(dr.IsNull(“LName“))                                          //Getting Value
{
//Code here…
}
DataRow[“LName“] = Convert.DBNull;         //Setting Value

इसके अलावा यदि हमें किसी SQL Query में Null Value को Check करना हो, तो WHERE Clause के साथ हमें निम्न Statement Use करना होता है:

WHERE LName IS NULL 

जबकि सामान्यत: इस Statement को निम्नानुसार भी लिखा जाता है:

WHERE LName = NULL  

लेकिन इस तरीके को Use नहीं करना चाहिए।

Handling Multiple Rows Updating

ये एक Tricky प्रक्रिया होती है। मानलो कि हमारे पास एक DataTable है, जिसकी तीन Rows को Change किया गया है। पहले Change के रूप में एक नया Row Insert किया गया है, दूसरे Change के रूप में एक Row को Modify किया गया है और तीसरे Change के रूप में एक Row को Delete किया गया है।

अब मानलो कि हमने DataAdapter Object के लिए InsertCommand, UpdateCommandDeleteCommand Methods को Specify किया है, जो कि Appropriate RowState Property की Value के आधार पर Call होते हैं।

मानलो कि इन तीनों Commands में से Insert Command Successfully Run हो जाता है, लेकिन UpdateCommand Fail हो जाता है। इस स्थिति में हम हमारी जरूरत के अनुसार निम्न में से कोई एक काम Perform करेंगे-

  • हम DeleteCommand को Execute करेंगे।
  • हम Execution को UpdateCommand के Fail होते ही रोक देंगे।
  • हम InsertCommand को भी Rollback करेंगे।

यानी हम हमारी जरूरत के अनुसार उपरोक्त तीनों में से किसी एक काम को Perform करेंगे। लेकिन एक Perfect Application में जरूरत के आधार पर हमें इन तीनों ही Operations को Perform करने की जरूरत पड सकती है, इसीलिए ADO.NET हमें DataAdapter Object के साथ ContinueUpdateOnError नाम की एक Property Provide करता है।

इस Property का Default मान false होता है और इस Property में false मान होने का मतलब ये है कि UpdateCommand के Execute होने पर यदि किसी तरह का Error Generate हो, तो DbConcurrencyException नाम का एक Exception Trigger होता है। परिणामस्वरूप DataAdapter Object ये Exception Trigger होते ही Execution को रोक कर Return हो जाता है।

यदि हम इस Property को true Value Set कर दें, तो उस स्थिति में DataAdapter Object Exception Trigger होने की स्थिति में भी Command को Execute करता है। इसका Default मान false होता है क्योंकि इस Property को false Set करने पर Update Operation या तो पूरी तरह से Successfully Complete होता है या फिर पूरी तरह से Fail होता है। इसीलिए यदि एक Operation Fail होता है, तो सभी Operations Fail हो जाते हैं। अत: इस Update को Atomic बनाने के लिए हमें इसे सामान्यत: Transaction के बीच Enclose करना होता है।

हालांकि ये जरूरी है कि ADO.NET हमें किसी तरह से इस बात की Information दे कि किस Row के लिए Error Trigger हुआ है और इस बात की जानकारी प्राप्त करने के लिए हम DataRow.HasErrors Property को Use कर सकते हैं। यदि किसी Row में Error होता है, तो उस Error की Description प्राप्त करने के लिए हम DataRow.RowError Property को Use कर सकते हैं।

इसी प्रकार से DataSet DataTable Objects के साथ भी हमें HasErrors Property प्राप्त होती है, जिसे हम इस बात की जानकारी प्राप्त करने के लिए Use कर सकते हैं, कि Global Level पर कोई Error Generate हुआ है या नहीं।

जब DataGridView Control का Data किसी DataRow से Bound होते समय DataRow में कोई Error Trigger हो, तो वह Particular Row एक Exclamation Mark के रूप में उस Particular Error को Show करता है साथ ही दिखाई देने वाला Tool Tip हमें Error की Description Show करता है। जब सभी Errors को Handle करने के लिए Code Specify कर दिया जाता है, तब हम DataRow, DataTable DataSet Objects के लिए ClearErrors() Method को Use कर सकते है।

लेकिन कुछ Special Situations में Error होने की स्थिति में हम न केवल Execution को रोकना चाहते हैं, बल्कि जो Statements Execute हो चुके हैं, उन्हें Rollback भी करना चाहते है। इस स्थिति को सामान्यत: Transactions के माध्‍यम से Handle किया जाता है।

ADO.NET with C# in Hindi - BccFalna.com: TechTalks in Hindi ये Article इस वेबसाईट पर Selling हेतु उपलब्‍ध EBook ADO.NET with C# in Hindi से लिया गया है। इसलिए यदि ये Article आपके लिए उपयोगी रहा, तो निश्चित रूप से ये पुस्तक भी आपके लिए काफी उपयोगी साबित होगी। 

ADO.NET with C# in Hindi | Page:501 | Format: PDF

BUY NOW GET DEMO REVIEWS