الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

مشكلة في ID

مغلق
بدأه ندى الصباح في 26 يوليو 2005 · 8 رد · 1,967 مشاهدة · في ADO.NET
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم

عند تخزين السجل الجديد يظهر سجل آخر برقم ID آخر مع العلم أن الID يعتبر Identity أي ترقيم تلقائي في قاعدة بيانات SQlServer (السبب عدم تحميل الداتا في بداية فتح الفورم) فما الحل لهذه المشكلة ؟ لماذا عندما أخزن السجل الجديد لأول مرة يظهر سجل آخر مكرر ؟

الأخ الغملاسي الكريم:

لقد وجدت لك مشاركة بنفس المشكلة تماما ولكن لم يكن فيها الحل فهل وجدت الحل لمشكلتك لأني أصادف نفس المشكلة الآن وجزاك الله خيرا

أنظر المشاركة:

/index.php?showtopic=58892

#2

السلام عليكم

الحل موجود بإذن الله , فقط أخبريني هل تستخدمين DataView على الجداول أم لا ؟

حتى أرتب الجواب وفقاً للمعطيات , السلام عليكم

تم تعديل هذه المشاركة بواسطة الغملاسي في 26 يوليو 2005 في 19:22

في المثال يتضح المقال

#3

لا.. لم أستخدم DataView ، لقد استخدمت DataAdapter و Dataset

#4

السلام عليكم

حسب تعاملي مع هذه المشكلة تبين لي أنني حينما أستخدم طريقة تحديث البيانات

بحيث إنشئ DataSet جديدة ثم أخذ القيم التي تم إدراجها أو تعديلها في الـ DataSet الافتراضية

وذلك عن طريق السلوك GetChanges أن يتم تكرار الصف Row بسبب عدم تمكن السلوك Merge

من معرفة أو مطابقة الصفوف ( الصف المضاف و المتكرر ) و عدم معرفتة لأخر Identity

في قاعدة البيانات و المشكلة تحدث بالتحديد عند إستخدامنا لهذا السلوك وهو Merge

الحلول المطروحة لهذه المشكلة كالتالي

أولاً هنالك ثلاثة حلول على حسب معلوماتي المتواضعة في هذا الفن .

الحل الأول

............................

هو إذا كانت قاعدة البيانات ليست بذاك الإزدحام من المستخدمين 100

وأن حجم قاعدة البيانات لم يتعدى الـ GB فيفضل أن لا نستخدم DataSet جديدة

و بكل بساطه نستخدم طريقة التحديث الكلاسيكية العادية بهذا الشكل

  Me.DAMain.Update(DsMain1, "MainSuspicion")
  Me.DAAccused.Update(DsMain1, "SusAccused")
   DsMain1.AcceptChanges()

الحل الثاني

.........................

إذا كانت طريقة الإضافة في قاعدة البيانات محددة على النماذج forms بحيث كل نموذج مختص لعمل ما

مثلاً نموذج فقط للإضافة و أخر للتعديل والتحديث و أخر للحذف وهلم جرى في هذه الحالة نستخدم السلوك Select للجدول

بحيث نختار منه طريقة القيم التي تم إدراجها في الـ DataSet مثلاً المضافة أو المعدلة أو المحذوفة المهم بهذا الشكل تكون

  Me.DAMain.Update(DsMain1.MainSuspicion.Select("", "", _
                      DataViewRowState.Added))
            Me.DAAccused.Update(DsMain1, "SusAccused")
          
            DsMain1.AcceptChanges()

من الملاحظ هنا أن الجدول الفرعي الابن Child Table لا يحتاج إلى السلوك Select لان المعني هاهنا الجدول الرئيسي Main Table

الحل الثالث

.................................

لو إفترضنا أن عدد المستخدمين كثر و قاعدة البيانات كبيرة الحجم و التي تعرف بـ multi-tiered application

فبِلا أدنى شك أن السلوك Merge مطلوب لتخفيف الحمل على قاعدة البيانات Bandwidth

فالحل المطروح هاهنا أن نقوم بحذف السطر المكرر عن طريقة السلوك RemoveAt

أولاً بالنسبةِ لي قمت بتعريف متغيرين بهذا الشكل

 Private InsertFlag As Boolean = False
 Private MissingIdentity As Boolean = False

الأول يخبرني أننا الآن في عملية الإضافة فمتا قام المستخدم بإضافة سطر جديد تحول هذا المتغير المنطقي إلى القيمة true

المتغير الثاني يتحقق قبل الإضافة هل عدد صفوف الجدول الرئيسي أصغر من واحد يعني صفر فهذا يعني أنني لا أملك أخر

Identity لذلك أسند القيمة true لهذا المتغير بهذا الشكل

'DataView count
            If Me.DVMain1.Count < 1 Then
                MissingIdentity = True
            End If

            'If you don't use DataView then your code should be 
            If Me.DsMain1.MainSuspicion.Count < 1 Then
                MissingIdentity = True
            End If

الان عند تحديث البيانات أشترط شرطين ان يكون كِلا المتغيرين يحملان القيمة True بهذا الشكل

  If InsertFlag AndAlso MissingIdentity Then
                DsMain1.MainSuspicion.Rows.RemoveAt(BindMBase.Position)
            End If

إذا تحقق الشرطان فهذا يعني أن التكرار حاصل لا محالة لذلك لابد أن احذف السطر الأول الذي يمثل الرقم صفر

من حيث عدد الصفوف فالعدد واحد هو في الـ Index صفر والثاني في الـ Index واحد وهلم جرى

وحتى لا يحدث لبس في الشرح أقول الخاصية Count ترجع القيم كالتالي إذا كان الجدول في الـ DataSet ليس به

صفوف Rows ستكون القيمة صفر , لكن الـ ManagerBase يعرف أن الصف الأول من حيث الـ Index في

الجدول يساوي صفر , هذا واضح !!

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

نرتبها فيه بهذا الشكل 0و1و2 أي أن الجدول ينسق صفوفه إبتداءً من الرقم صفر

وبهذا فإن الصف الأول في الجدول يكون في الخانة صفر ....

إنتبهو يا أخوان أنا أتكلم عن الـجدول في الـ DataSet

وليس عن الجدول في الـ DataBase وعن ترتيب الصفوف

بشكل منطقي لا عن الـ ID في الجدول.

المهم ان الصف المتكرر يقبع في المقدمة فنقوم بإزالته عن طريق الـ ManagerBase الذي يتم بواسطته

التنقل عبر الصفوف بهذا الشكل تم تعريفة

 Dim BindMBase As BindingManagerBase

ثم في حدث تحميل النموذج أقوم بربطه بالجدول الرئيسي بهذا الشكل

 BindMBase = Me.BindingContext(DVMain1) 'DataView Binding
            'If you not useing DataView Your code should be
            BindMBase = Me.BindingContext(DsMain1, "MainSuspicion")

وعملية التحديث بالشكل النهائي ستكون بهذا الشكل

 Public Sub UpdateDataSet()
        BindMBase.EndCurrentEdit()
        Me.BindingContext(DsMain1, "SusAccused").EndCurrentEdit()
        Try
            Dim DSC As New suspicion.DSMain
            DSC = CType(DsMain1.GetChanges, suspicion.DSMain)
            Me.DAMain.Update(DSC)
            Me.DAAccused.Update(DSC)
            DsMain1.Merge(DSC)
            'check if the there's a duplicate Row
            If InsertFlag AndAlso MissingIdentity Then
                DsMain1.MainSuspicion.Rows.RemoveAt(BindMBase.Position)
            End If
            MissingIdentity = False
            DsMain1.AcceptChanges()
            'UpdateDisplay()
            Me.SBInfo.Text = "تم تحديث البيانات بنجاح"
            btnNew.Enabled = True
            EnableNButtons()
            InsertFlag = False
        Catch ex As Exception
            Throw ex
        End Try
    End Sub

ومن المنطق بلا شك أننا بعد عملية التحديث أو أن المستخدم إلغا الإضافة أو التعديل أو ما شابه ذلك من التعامل مع الـ DataSet

فإنه لابد أن نرجع قيمتي كلا المتغيرين إلى القيمة False كما هو مبين في النصوص البرمجية في الأعلى

حتى لا نقوم بحذف سطر موجود بسبب ترك قيمتي المتغيرين على الحالة True .

هذه كل الحلول التي أعرفها و بلا شك ما أجهله كثير

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

حم حم نسيت أن أخبركم بشيء هو أنه ليس بشرط أن نستخدم المنطق الأول حتى ولو كان عدد المستخدمين قليل أو البيانات على حدٍ سواء

كما هو حالي في العمل 4 موظفين ( ثلاثة في إجازه سنوية) واحد متململ من البرنامج :blink:

مع ذلك أستخدم الطريقة الثالثة كونها أفضل بكل المقاييس مع خطورتها عند هفواتنا و غفلتنا .

هذا والله أعلى و أعلم

السلام عليكم

في المثال يتضح المقال

#5

أولا ... ألف ألف مبروك على اللقب الجديد.. (ماشاء الله)

والمفروض كان " علامة VB.Net " (لاحظ الشدة على لام علامة)

ٌٌ

لاأعرف كيف أشكرك على كل هذا المجهود الكبير في الشرح والرد والتوضيح .. بارك الله فيك

ولكني أريد ثقلة أخرى وهي أن ... آه

بصراحة (بس لاتقول لأحد) حاولت تطبيق ماسبق ولكن ماعرفت

وأرفقت لك مثال + قاعدة بيانات SQL Server وأريدك أنت أن تطبق ماسبق عليه (ما يامر عليك عدو)

المثال عبارة عن شاشتين لأسماء المدن:

الشاشة الأولى تتعامل مع جدول يحتوي Identity ، التعديل المطلوب على هذه الشاشة هو الموضح في السؤال في مشاركة 1

أما الشاشة الثانية فتتعامل مع جدول لا يحتوي على Identity ، وهنا أريد طلب جديد وهو كيفية إحضار آخر رقم ID بشكل يدوي (أيضا حاولت هنا أن أطبق ذلك ولم أستطع)

مع الأخذ في الاعتبار أن البرنامج على الشبكة وعليه ضغط كبير

مرة أخرى لاأعرف كيف أشكرك .. وجزاك الله خيرا .. وأنا بفارغ الصبر أنتظر

تم تعديل هذه المشاركة بواسطة ندى الصباح في 27 يوليو 2005 في 20:38

#6

...

Project.zip

تم تعديل هذه المشاركة بواسطة ندى الصباح في 27 يوليو 2005 في 20:40

#7

السلام عليكم

حياكِ الله و لا شكر على واجب

دعينا نناقش الموضوع بإختصار

أولاً يستحسن و يفضل أن نستخدم SqlClient بدل من oledb عندما تكون قاعدة البيانات SQL

بسبب عدم إستخدام المزود Provider من قبل SqlClient وهذا يعني سرعة في معالجة البيانات . (فائده)

طيب بالنسبة للطلب الثاني معرفة أخر ID يكون كالتالي

إذا كان الـ ID على نمط AutoNumber or autoIncrement Seed فإننا نحتاج فقط الوظيفة التالية من SQL وهي

SELECT @@IDENTITY

هذه الوظيفة تعمل عند الإضافة سواءً من Insert أو Select Into أو bulk لذلك أخر ID سنعرفه بعد عملية الإضافة

المثال في النموذج CityForm1.vb

ولو كان الـ ID ليس على النمط هذا ولكن يدخل بشكل تصاعدي لكن الحل هو

SELECT Max(CityID) FROM City_Not_Identity

المثال في النموذج CityForm2.vb

لكن بما أن الإثنان لم يتضمنا في المشروع (فكان من الأفضل أن نجعل ID أخر يعتني بتسلسل الجدول )

وبه نستطيع معرفة أخر صف أُدرج في قاعدة البيانات .

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

تمت فيها عملية الإدخال بهذا الشكل

SELECT CityID  FROM City_Not_Identity
WHERE lastTimeIdentity = (SELECT Max(lastTimeIdentity) FROM City_Not_Identity)

وهو يعني أختر رقم الـ ID من الجدول City_Not_Identity بشرط أن يكون الوقت الأعلى في العامود lastTimeIdentity

و بهذا لو إفتراضنا أن الـ ID 3 أدخل بعد الـ ID 5 فإن أخر ID سيكون 3 بلاشك

المثال في النموذج CityForm2.vb

فلو كنتي تريدين أعلى ID فإستخدمي الكود التالي

SELECT Max(CityID) FROM City_Not_Identity

على العموم الحل موجود في الملف المرفق

لا تنسي أن تلصقي قاعدة البيانات المرفقة كونها تحمل عامود إضافي في الجدول City_Not_Identity

هذا والله أعلم

السلام عليكم

LastIdentity.zip

1

في المثال يتضح المقال

#8

جزاك الله خير الأخ العزيز الغملاسي

ومهما قدمت لك من الشكر لن أوفي

شكرا لجهودك ومتابعت مشكلتي والحمد لله نجح معي المثال

وفقك الرحمن وأدامك لهذا المنتدى الكريم

والسلام عليكم ورحمة الله وبركاته

وأعتذر على تأخر الرد

تم تعديل هذه المشاركة بواسطة ندى الصباح في 30 يوليو 2005 في 18:06

#9

السلام عليكم

لا شكر على واجب , و بالتوفيق والسداد إن شاء الله

في المثال يتضح المقال

هذا الموضوع مغلق.

مواضيع مشابهة