منتدى فيجوال بيسك لكل العرب | منتدى المبرمجين العرب

نسخة كاملة : كيف اقوم بقفل الملف الذي يستخدمه احد المستخدمين
أنت حالياً تتصفح نسخة خفيفة من المنتدى . مشاهدة نسخة كاملة مع جميع الأشكال الجمالية .
السلام عليكم ورحمة الله

قاعدة بيانات SqlServer
فتح المستخدم احمد احد الملفات للتعديل ولم يقفل شاشة التعديل وقام المستخدم عمر بفتح الملف لاجراء تعديل عليه

ما الاجراء المتبع لمنعه من فتح الملف حتى يقوم احمد بقفل شاشة تعديل هذا الملف
وعليكم السلام ورحمة الله وبركاته
أن تصع جدول جديد في قاعدة البيانات تسجل فيه العملية المفتوحة للتعديل 
فذا تمت مسحها منه
وأ] مستخدم يريد التعديل على عملية ما عليه أن يشيك أولا هل هي موجودة في سجل التعديلات أم لا 
فإن لم تكن موجودة سمح له بفتحها .. وإلا فلاا 



أو تضع عمود إضافي في نفس الجدول الخاص بالعملية فإذا ما تم فتح ذاك السجل لتعديل وضع في ذاك العمود رقم 1 واذا ما انتهى من التعديل أو قام بإلغاء عملية التعديل وضع صفر مثلاً ..
فمتى ما جاء مستخدم ليعدل على ذاك السجل أولاً يشيك على تلك القيمة اذا كانت واحد يمنع من الوصول حتى تنتهي تلك العملية
شكرا اعرف هذا الحل ولكن هناك حل من صميم تصميم قاعدة البيانات
له علاقة بالعملية Transaction لو احد يعرف ومر به الموضوع
(20-04-23, 05:32 AM)ابو محمد محمد محمد كتب : [ -> ]شكرا اعرف هذا الحل ولكن هناك حل من صميم تصميم قاعدة البيانات
له علاقة بالعملية Transaction لو احد يعرف ومر به الموضوع


الـ Transaction ليس لها علاقة لا من قريب ولا من بعيد بمنع مستخدم من إجراء تعديل أو الوصول إلى سجل معين.

هذف الـ Transaction هو تحقيق مبداء تكامل البيانات, إما أن تنجح كامل العملية أو تفشل كامل العملية، سواء عملية تحديث أو حذف أو إدخال أو عمليات مختلطة ومتعددة بين هذا وذاك.
أما الكل أو فلا.



يوجد نوع بيانات لحقل وهو Timestamp

هناك آليه تمنع التظارب بين المستخدمين بواسطة التحقق من الحقل من نوع ( Timestamp )
لا يهم اسم الحقل المهم انه موجود ضمن حقول الجدول

مثال :
محمد فتح النافذة وبداء يغير في البيانات على الشاشة ولكن لم يضغط على زر الحفظ بعد، إنشغل أو ذهب إلى مكان.

مصطفى في نفس اللحظة فتح نفس السجل وعدل على البيانات وقام بالحفظ مباشرتاً.

محمد عاد بعد 10 دقائق، ثم ضغط على زر الحفظ، ستظهر له رسالة تخبرة بأن البيانات التي تحاول التعديل عليها قد تغيرت، ويجب عليك تحميلها من جديد إذا كنت ترغب في تعديلها.
[attachment=28886]



نوع الخطاء هو : Concurrency violation
بمعنى ( انتهاك التزامن )


المفترض من المبرمج أن يتحقق عند تطبيق جملة ( التحديث أو جملة الحذف ) فقط (  UPDATE  و   DELETE  )  غيرها لا يهم
الــ  (  UPDATE  و   DELETE  )  هم فقط الذين من الممكن أن ينتهكو التزامن.


كيف يتحقق المبرمج : ( بهذة الطريقة عند تنفيذ الجملة )
[attachment=28887]

الـ Original_itm_Timestamp هو متغير يأخذ قيمة الحقل itm_Timestamp الأصلية عند أول عملية جلب لهذا السجل
وعندما تريد تنفيذ عملية حفظ أو حذف طبق الجملة في الأعلى للتأكد من أن السجل لم يقم أحد بتغيير منذ آخر لحضة قمت بجلب السجل


الحقل من نوع Timestamp للعلم 
قاعدة البيانات هي من تعدل قيمة هذا الحقل في كل مرة يحدث تغيير في أي حقل من حقول السجل
الـ Timestamp هو عبارة عن تاريخ ووقت ولكن بصيغة Binary وهو مضمون انه لن يتكرر أبداً في نفس الجدول.





إذا كنت تبحث عن آليه لقفل السجل فيجب عليك تطبيق فكرت أخي Taha Okla ولكن بأسلوب مختلف :
لم أجربها من قبل ولكن هذة الفكرة أجدها ممتازة ، وهي :

عند فتح نافذة التعديل على سجل، هذة النافذة ترسل مثلاً كل 30 ثانية أمر تحديث في جدول مختلف بأن هذا السجل تحت التعديل من ( تضع تاريخ ووقت لعملية قفل السجل ) والنافذة يجب أن ترسل كل 30 ثانية ( تاريخ جديد - ينتهي بعد 5 دقائق مثلاً ) أنها مازالت في وض التعديل.
لو فرضاً حدث خلل في البرنامج الشخص الذي يقوم بالتعديل - أو فقد الإتصال وقام بإطفاء الجهاز ، بهذا الشكل لن يبقى السجل في وضع القفل.
لأنك عنما تريد تعديل سجل وتريد قفلة ستتأكد من آخر تاريخ ووقت تم قفل السجل فيه ، إذا كان أكبر من دقيقة واحدة يعني أنه لا توجد هناك نافذة ترسل أمر إبقاء السجل في وضع القفل.

أرجوا أن تكون الفكرة وصلت، والأفكار كثير.




كل عام وأنتم بخير...
استاذ عبدالله الدوسري لعل الاخ يقصد هذا الموضوع SQL Server When to use RowLOCK, UPDLOCK etc

الترجمة المبدئية
يضمن قفل مستوى الصف ROWLOCK أنه عندما يحصل المستخدم على الصف المحدث ، فلن يتم تعديله من قبل مستخدمين آخرين خلال هذا الوقت.
لذلك ، يمكن أن تضمن عمليات التأمين على مستوى الصف اتساق البيانات وتحسين تزامن عمليات البيانات.
ROWLOCK يخبر SQL Server لاستخدام أقفال على مستوى الصف فقط.


ليست لدي الخبرة للدخول في هذا الموضوع
(21-04-23, 06:53 AM)foo كتب : [ -> ]استاذ عبدالله الدوسري لعل الاخ يقصد هذا الموضوع SQL Server When to use RowLOCK, UPDLOCK etc

الترجمة المبدئية
يضمن قفل مستوى الصف ROWLOCK أنه عندما يحصل المستخدم على الصف المحدث ، فلن يتم تعديله من قبل مستخدمين آخرين خلال هذا الوقت.
لذلك ، يمكن أن تضمن عمليات التأمين على مستوى الصف اتساق البيانات وتحسين تزامن عمليات البيانات.
ROWLOCK يخبر SQL Server لاستخدام أقفال على مستوى الصف فقط.


ليست لدي الخبرة للدخول في هذا الموضوع


فكرة جميله أخي foo ( لكن )
ROWLOCK لها إستخدامات أخرى، ولم يتم تصميمها لقفل السجل بالطريقة التي يريدها الأخ ابو محمد

ROWLOCK فعلاً تقوم بقفل السجل على مستوى السجل، تم تصميمها لقفل السجلات أثناء تنفيذ العمليات، مثل تنفيذ عمليات تحديث ثم يليها عمليات ادخال ثم يليها عمليات حذف، بهذا الشكل.
والهدف هو منع وصول المستخدم لهذة السجلات أثناء تنفيذ مثل هذا النوع من العمليات،


تخيل أنا موظف : ( البيانات الصحيحة كالتالي )
رصيد إجازاتي مثلاً : 50
عدد أيام الخروج : 0

قمت بالخروج في إجازة لمدة 50 يوم ( ولكنها لا تسجل مالياً إلى في نهاية كل شهر مثلاً )

بعض العمليات الإدارية مثلاً تقوم بها بالجملة لكل الموظفين وليست لموظف معين.
لأمور ماليه قام موظف الإدارة ببداء عمليات حسابية ( إجازة وحظور ورواتب وتأخير ...إلخ من الأمور الإدارية التي تؤثر على رصيد الإجازة مثلاً )
الموظف بداء العملية ...
أنا في نفس الوقت إستعلمت عن بياناتي .... ليس من المنطقي ان أجد رصيد إجازتي ( 0 ) بينما عدد أيام الخروج أيضاً ( 0 ).
أنا قمت بالإستعلام بينما هناك عملية تحدث في قاعدة البيانات لم تكتمل بعد، يمكن تأخذ دقائق أو 10 أو 30 دقيقة حتى تنتهي العملية، المهم.

هذة مجرد مشكلة بسيطة أنا أراها على شاشة الكمبيوتر.
المصيبة إذا كانت هناك أنظمة بنكية أو مالية أو أي شيء مهم، متصله قامت بالإستعلام وتعتمد على هذة البيانات، ( لن أشرح لك عن كمية الفوضى التي من الممكن أن تحدث )

لذلك جاء الحل بإستخدام ( ROWLOCK  ) 
فقط يتم قفل السجلات المطلوبة عند بداء العملية وينتهي مع إنتهاء العملية، حتى تصبح البيانات منطقية، ومتكاملة. ، بالإضافة إلى إستخدام الـــ Transaction ، يتم تأمين صحة ودقة البيانات.
لأن الـــ Transaction لوحدة لا يمنع الوصول للبيانات.


لم يتم عمل ROWLOCK  لقفل السجل بينما البيانات على الشاشة أمام  المستخدم ، وممكن يطول الأمر إلى ساعة أو حتى أكثر والنافذة مفتوحة بإستخدام هذة الطريقة.
إذا إستخدمتها بهذة الطريقة ، تسمة ( bad practice ) ( سوء الممارسة ).




أفضل طريقة هي بإستخدام حقل زمني يبين إذا كان هذا السجل مقفل أو لا!!!
أول ما تفتح نافذة تحرير السجل ، مباشرتاً تقوم بإنشاء سجل إذا لم يكن موجود في جدول خاص ( مثلاً باسم : TblRowsLock ) يدل (  أن هذا السجل بالرقم الفلاني يتم تحريرة الأن بهذا الوقت والتاريخ بواسطة المستخدم الفلاني  )
بعدها ( ما دامت النافذة مفتوحة ) في كل دقيقة يتم تحديث السجل نفسة السابق الموجود في جدول ( TblRowsLock ) بالوقت الجديد، ( بمعنى متى آخر مرة هذة النافذة قامت بقفل السجل )
ولا تنسى عند إغلاق نافذة التحرير ( إزالة الوقت الموجود في الجدول - TblRowsLock  ) حتى تزيل القفل مباشرتاً، ولا تنتظر دقيقة لفتح السجل من جديد.
بعد إغلاق نافذة التحرير :
السجل الموجود في جدول ( TblRowsLock ) سيبقى، لكن النافذة اغلقت ولن يتم تحديث الوقت في السجل.
وبذلك عندما تريد فتح نافذة التحرير، يجب أن تسأل عن الجدول ( TblRowsLock ) إذا كان يحتوي على سجل قفل لهذا السجل المراد تحريرة ، أن لم يجد فهذا يعني لا يوجد قفل، أن وجد سجل ، يتم مقارنة حقل ( آخر تاريخ للقفل ) في جدول ( TblRowsLock ) مع الوقت الحالي، إذا كانت أكبر من ( 60 ثانية مثلا ) ، هذا يدل على أنه لايوجد هناك احد يقوم بتحرير هذا السجل، إذا كانت أقل من ( 60 ثانية ) فهذا يدل على أنه هناك نافذة تحرير مفتوحة الآن.

والجميل في هذة الطريقة انها بسيطة، ولن يتم قفل السجل حتى عن طريق الخطأ لو تم فتح نافذة التحرير، وتجمد النظام بالكامل أو تم إغلاق الجهاز سيرجع السجل كما كان لأن الوقت هو العامل الأساسي لعملية القفل، بعد دقيقة من إغلاق نافذة التحرير.
سوف اجرب طرقكم

انا لم استخدم SqlServer من قبل لهذا اسأل والقصة ومافيها اعتقد انني قرأت ان استخدام الـ Transaction  يمنع المستخدم من الوصول الى السجل كما يقوم ايضا باجراء عمليات متعددة

في قواعد البيانات التي استخدمها كنت اقوم باستدعاء السجل بالطريقة التالية

كود :
SELECT * FROM kv WHERE k = 1 With Lock;

هذا يمنع المستخدم من عرض السجل حتى يقوم المستخدم الاول بقفل الاتصال بهذا السجل

وتقريبا مر بي شئ للسكيوال سيرفر شبيه به كالتالي

كود :
SELECT * FROM kv WHERE k = 1 FOR UPDATE;

واهل مكة ادرى بشعابها فانتم اعلم مني بهذا النوع من قواعد البيانات
في حال تعديل سجل سجل الن تقع في مشكلة من أجل تعارض البيانات (في حال تستخدم اتصال OnLine)
في حال تقوم بتعديل عدة سجلات بنفس الوقت قد يحدث التعارض  ..

ما هي الحالات التي تستدعي أن تقفل من أجلها سجل ما حتى يتم تعديله أو قيام عملية عليه... ؟؟ !!!

في حال برنامج مبيعات لجمعية أو مول :: ليس منطقي ،، حيث أنه لن يتم بيع سلعة إلا بعد أن تكون وصلت ليد البائع..
فإذا أعطاك البرنامج تنبيه أن هذه السلعة غير موجودة في المستودعات ولا يوجد الكمية الكافية للبيع (قل له أزحط أنت واللي صنعك)..

في حال برامج مبيعات الجملة للشركات والفروع والمخازن، بالعادة البائع يقوم بإعداد مذكرة(طلب شراء، بيع) ترسل لأمين المخازن ويقوم هو بتجهيز الطلبية وإعلام البائع بتجهيزها فيقوم البائع بتصدير الطلبية لفاتورة مبيعات فعلية..

في حالة عميل البنوك لن تستطيع الوقوف أمام كونترين بنفس الوقت.. 
خاصة بعد الاجراءات الصارمة التي تتخذها البنوك من طلب اثباتات لا يمكن توفرها مع شخصين بنفس الوقت.
وفي حال وجود وكالة قانونية لن يتم تنفيذ العملية بنفس الوقت إلا بعد ارسال تلك الوكالة للدراسة.. حتى لو قمت بعدة عمليات (حتى لو كانت متشابهة) فكل عملية ستقوم بارسال تلك الوكالة للدراسة هل يسمح له باستخدام تلك الوكالة أم لا..

صرف المعاشات، طلب اجازات أو الغائها : نفس ما سبق.

الشيء الوحيد أن تقوم من أجله بقفل سجل ما :
هو التعديل على كمية مخزون (كمثال) نتيجة بيع أو شراء أو مردودات أو تالف أو نقص ما ..
وهذه العملية غير صحيحة إطلاقاً - 
الصحيح هو : أن تسجل سجل جديد بكل عملية تقوم بها..
سجل بالاضاقة ، سجل بالمسحوبات، سجل بالمردودات ... إلخ
والبرنامج يقوم بعملية حساب المخزون الحالي من نتيجة تلك السجلات وليس بجلب رقم ثابت ..

===============
الحالة الوحيدة التي تستدعي قفل السجلات 
هي تعديل مجموعة سجلات مرة واحدة ..
مثال : إدراج وتعديل درجات طلاب في صف ما من مدرسة ما (كما في بعض البرامج الخاصة بالمدارس، وقليل جداً من برامج الموارد البشرية)..
حيث أنهم يقومون بجعل البرنامج يعرض سجلات الصف كاملاً كما كأنك تفتح لتعرض الجدول من قاعدة البيانات كما هو وتسمح بالتعديل عليه كاملاً وكأنه صفحة اكسل.

بينما الأفضل لو تم تعطيل تلك الخاصية والسماح بتعديل سجل سجل، ومنع استيراد البيانات الخارجية من جداول الاكسل..
وبهذا لن يتم التعارض بأي عملية مع أي عملية أخرى.

= == 
يوجد الكثير من الحالات .. ولكن الاجراءات المتخذة مع تطور القوانين واسلوب التعامل 
جعلت تلك الحالات تُسَّيَر بنفس الطريقة ..

تنتميط عمل البرنامج يجعل من غير الضروري إقفال أي سجل أثناء التعديل..

لا أعرف إن كان هناك شيء آخر يستلزم ذاك التفكير ..
بالضبط تنفع لبيانات الطلاب او الموظفين فالافضل هو عند فتح ملف طالب للتعديل ان اخبر المستخدم الاخر ان هذا الملف يتم تعديله الان ويجب ان ينتظر الانتهاء منه

 عمل معي هذا المفتاح وقفل السجل

كود :
SELECT * FROM  People  WITH (UPDLOCK) WHERE id = 1  ;

ولكن يبدو انه لا يعمل الا اذا كان على نفس الاتصال فعلى السيرفر ومن الكويري يعمل ويقفل السجل عند محاولة فتح نفس الملف بكويري اخر حتى الخروج من عملية العرض للبيانات اما في الفيجوال ستوديو لازال لا يعمل