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

مثال عملي على Linq To DataSet فى C#

بدأه عمرو الصعيدي في 5 أبريل 2010 · 11 رد · 5,048 مشاهدة · في Microsoft Visual C#.NET
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

اخوانى هذا المثال والشرح اقتبسته من الأخ (samerselo) مشرف فى منتدى الفيجوال بيزك حيث أن الشرح الأساسى مشروح بال VB.NET ولكنى هنا سوف أستخدم ال C#

وهذا هو الرابط فى منتدى الفيجوال بيزك

http://vb4arab.com/vb/showthread.php?t=13315

نبدأ باسم الله

الهدف من المثال

1. حفظ بيانات DataSet في ملف xml واستعادتها منه والتعامل معها بدون الحاجة لوجود قاعدة بيانات

2. الاستعلام من الـ DataSet باستخدام Linq ومن أكثر من جدول وإدخال بعض الحسابات في جملة الاستعلام واستخدام عبارة Join لمنع التكرار الخاطئ للبيانات

3. استخدام Lambda Expressions للقيام بالحسابات من أجلنا والاستفادة من ميزة رفع المتغيرات

4. إظهار نتيجة استعلام Linq في DataGridView مباشرة

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

افتح أي إصدار من فيجول ستوديو 2008 وأنشئ مشروعا جديدا من نوع Windows Forms Application ثم من قائمة Project اختر الأمر Add New Item وأضف DataSet للمشروع وقم بتسميتها MyDataSet

في محرر التصميم الرسومي لمجموعة البيانات انقر بزر الفأرة اليميني واختر الأمر DataTable من قائمة Add في قائمة السياق ثم قم بإعادة تسميته ليصبح اسمه Customers

أضف للجدول Customers الحقول التالية مع الخصائص الموضحة

الحقل ID الخاصية AutoIncrement بالقيمة True والخاصيتان AutoIncrementSeed و AutoIncrementStep كلتاهما إلى القيمة 1 و نوع البيانات System.Int32 ثم انقر بزر الفأرة اليميني على الحقل ID واختر الأمر Set Primary Key من قائمة السياق لتحديد الحقل كمفتاح أساسي

الحقل CustomerName نوع البيانات System.String و MaxLength بالقيمة 25

الحقل CurrentAccountNumber نوع البيانات System.String و MaxLength 25

حيث أن الحقل ID هو معرف الزبون و CustomerName هو اسم الزبون والحقل CurrentAccountNumber هو رقم الحساب الجاري لدى المصرف

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

الحقل WadeaaNumber بنوع بيانات String

الحقل CustomerID بنوع بيانات Int32

الحقل InterestRate بنوع بيانات Decimal و NullValue مساوية لـ 7.5

الحقل WadeeaPeriod بنوع بيانات Int16 و BullValue مساوية لـ 3

الحقل StartDate بنوع بيانات DateTime

الحقل WadeaaAmount بنوع بيانات Int32 و NullValue بقيمة 10000

حيث WadeaaNumber هو رقم الوديعة و CustomerID هو حقل مرتبط بجدول الزبائن و InterestRate نسبة الفائدة و WadeeaPeriod فترة الوديعة بالأشهر و StartDate تاريخ فتح الوديعة و WadeaaAmount قيمة الوديعة

سنضيف الآن علاقة بين الجدولين: انقر بزر الفأرة اليمني على الجدول Customers ومن القائمة الفرعية Add اختر Relation ثم اضبط Parent Table إلى Customers و Child Table إلى Wadaeaa ثم اختر Key Columns ليضم الحقل ID فقط و Foreign Key Columns ليضم الحقل CustomerID فقط ثم اختر الخيار Both Relations And Foreign Key Constraint ثم اضغط Ok من أجل حفظ العلاقة ثم اختر الأمر Save All من القائمة File

post-207223-12704307135168_thumb.jpg

انتقل إلى محرر النماذج الخاص بـ Form1 واجعل مساحة Form1 كبيرة كفاية لتتسع لـ 2 × DataGridView مع شريط أدوات وبعض التحكمات الأخرى التي سنضيفها لاحقا ثم انتقل لنافذة Data Sources واسحب الجدول Customers ثم ألقه على سطح Form1 فيتم إضافة DataGridView و شريط أدوات للنافذة

من نافذة Data Sources انقر إشارة + بجانب الجدول Customers لتظهر لك قائمة بالحقول الخاصة به كما نلاحظ وجود نسخة من الجدول Wadaeaa كجدول فرعي ضمن Customers وذلك بسبب العلاقة التي قمنا بإنشائها بين الجدولين الآن قم بسحب الجدول Wadaeaa الموجود كجدول فرعي لـ Customers وليس الجدول الخارجي إلى سطح Form1 ليتم إنشاء DataGridView أخرى على النافذة ثم قم بتنسيق النافذة بشكل جيد وتأكد من أن الـ DataGridView الخاصة بـ Customers في الأعلى و الأخرى في الأسفل

post-207223-12704309491097_thumb.jpg

اختر CustomersDataGridView وانقر على السهم الصغير الذي يظهر في زاويتها اليمينية العليا واختر الأمر Edit Columns واضبط الخاصية Visible للحقل ID إلى False ثم كرر العملية بالنسبة للحقل CustomerID في WadaeaaDataGridView

post-207223-12704315488012_thumb.jpg

في شريط الأدوات في الأعلى انقر بزر الفأرة اليميني على زر الحفظ – يمتلك أيقونة قرص – واختر الأمر Enabled لتفعيله ثم انقر عليه نقرا مزدوجا لننتقل إلى محرر الكود ثم أدخل الكود التالي في حدث النقر على زر الحفظ حيث نستخدم الوظيفة WriteXml لتخزين محتويا مجموعة البيانات في ملف xml

private void customersBindingNavigatorSaveItem_Click(object sender, EventArgs e)
        {
            try
            {
                myDataSet.WriteXml(@"c:\TestData.xml");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

نشئ إجراء لمعالجة الحدث Load للنموذج وأدخل فيه الكود التالي الذي سيقوم بتحميل البيانات من ملف xml لاحظ ظهور رسالة خطأ عند تشغيل البرنامج لأول مرة وقبل حفظ البيانات حيث أن ملف البيانات لم يتم إنشاؤه بعد وهذا السبب في استخدام بلوك Try … Catch من أجل اصطياد الخطأ وتجنب إفشال عملية بدء البرنامج وقد استخدمنا الوظيفة ReadXml لتحميل البيانات من ملف xml إلى مجموعة البيانات

        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                myDataSet.Clear();
                myDataSet.ReadXml(@"c:\TestData.xml");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

تم تعديل هذه المشاركة بواسطة amr.alsaidy في 5 أبريل 2010 في 04:39

4

 وممّا زادنـــي شرفــاً وتيهــاً   **  وكدت بأخمصي أطأ الثريّا

دخولي تحت قولك يا عبادي  **   وأن صيّرت أحمد لي نبيّـاً

#2

post-207223-12704318719226_thumb.jpg

شغل البرنامج وأدخل فيه بعض البيانات في كلا الـ DataGridView وتأكد من أنك قد قمت بتعبئة جميع الحقول في كلتا شبكتي البيانات وقم بالحفظ وأغلق البرنامج ثم أعد فتحه من جديد للتأكد من أن عملية الحفظ قد تمت بشكل صحيح وانتبه إلى أن الحقل WadeeaPeriod هو عبارة عن عدد أشهر فترة الوديعة لذا حاول الالتزام بالقيم 1 أو 3 أو 6 أو 12 كقيمة لهذا الحقل من أجل تجربة إجرائية الاحتساب لاحقا

post-207223-12704319036488_thumb.jpg

نريد الآن إظهار قيم الاحتسابات الخاصة بكل وديعة عند المرور عليها وكذلك تاريخ استحقاق هذه الوديعة

أضف أربعة حقول نصية للنافذة ورتبها أسفل شبكتي البيانات وأعطها الأسماء التالية txtEndDate لتاريخ الاستحقاق و txtInterest لقيمة الفائدة و txtRayaa لضريبة الريع و txtIdara لضريبة الإدارة المحلية

أضف الاستيراد التالي في بداية ملف الكود الخاص بـ Form1 من أجل تمكيننا من استخدام الوظائف الموجودة به

using Microsoft.VisualBasic;

أضف ال class التالى فى بداية الكود الخاص بـ Form1 من أجل تمكيننا من استخدام Lambda Expressions فى ال c#

        public static class Linq
        {
            // Returns the given anonymous method as a lambda expression
            public static Expression<Func<T>>
                Expr<T>(Expression<Func<T>> f)
            {
                return f;
            }

            // Returns the given anonymous function as a Func delegate
            public static Func<T>
                Func<T>(Func<T> f)
            {
                return f;
            }

            public static Func<T, R>
                Func2<T, R>(Func<T, R> f)
            {
                return f;
            }
        }
2

 وممّا زادنـــي شرفــاً وتيهــاً   **  وكدت بأخمصي أطأ الثريّا

دخولي تحت قولك يا عبادي  **   وأن صيّرت أحمد لي نبيّـاً

#3

ثم أضف الإجراء التالي كإجرائية للاحتساب

        private void DisplayWaeaaCalcs(int Amount, DateTime StartDate, DateTime EndDate, decimal Interest)
        {
            long DaysNum = DateAndTime.DateDiff(DateInterval.Day, StartDate, EndDate, FirstDayOfWeek.System, FirstWeekOfYear.System);

            decimal Rayaa = 1;

            var Rayya_Calc = Linq.Func2((decimal Intrst) => Math.Ceiling((Intrst * 7.5m) / 100));
            var Idara_Calc = Linq.Func(() => Math.Ceiling(Rayaa * 10 / 100));
            var Intrst_Calc = Linq.Func(() => Math.Ceiling(Amount * DaysNum * Interest / 36500));

            decimal Intr = Intrst_Calc();
            Rayaa = Rayya_Calc(Intr);
            decimal Ida = Idara_Calc();

            this.txtEndDate.Text = EndDate.ToString("dd/MM/yyyy");
            this.txtInterest.Text = Intr.ToString("#,###.00");
            this.txtRayaa.Text = Rayaa.ToString("#,###.00");
            this.txtIdara.Text = Ida.ToString("#,###.00");
        }

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

من أجل أن نقوم باحتساب القيم الموافقة لكل وديعة عند المرور عليها سنقوم بعمل إجراء معالجة للحدث CellEnter لكلا شبكتي البيانات بإجراء واحد – أدخل الكود التالي كإجراء لمعالجة الحدث CellEnter لكلا الشبكتين

        private void wadaeaaDataGridView_CellEnter(object sender, DataGridViewCellEventArgs e)
        {
            try
            {
                var EdDat = from a in myDataSet.Wadaeaa
                            where (a.CustomerID ==Convert.ToInt32(this.customersDataGridView.CurrentRow.Cells[0].Value))
                                  && (a.WadeaaNumber == this.wadaeaaDataGridView.CurrentRow.Cells[0].Value)
                            select new
                            {
                                a.WadeaaNumber,
                                a.WadeaaAmount,
                                a.StartDate,
                                EndDate = DateAndTime.DateAdd(DateInterval.Month, a.WadeeaPeriod, a.StartDate),
                                a.InterestRate
                            };

                if (EdDat.Count() > 0)
                {
                    DisplayWaeaaCalcs(EdDat.First().WadeaaAmount, EdDat.First().StartDate, EdDat.First().EndDate, EdDat.First().InterestRate);
                }
            }
            catch (Exception ex)
            {
                this.txtEndDate.Text = string.Empty;
                this.txtInterest.Text = string.Empty;
                this.txtRayaa.Text = string.Empty;
                this.txtIdara.Text = string.Empty;
            }
        }

ويتم اضافة الحدث لكل من الشبكتين كما فى الصوره

post-207223-12704467009594_thumb.jpg

في البداية قمنا بإنشاء استعلام Linq للحصول على القيم الخاصة بالوديعة التي نقف عليها حيث أن المتغير a مرتبط بالجدول Wadaeaa ثم في قسم Where ضبطنا الشرط بحيث يجلب الاستعلام فقط الودائع الخاصة بزبون معين عن طريق التأكد من أن قيمة الحقل CustomerID مساوية لقيمة ID الخاصة بالزبون من خلال قراءة قيمة الخلية المناسبة في السطر الحالي وتتمة للشرط وبنفس الطريقة قمنا بضبط الشرط كي يجلب الوديعة ذات الرقم المراد ثم يأتي قسم Select لنحدد فيه قائمة الحقول التي نريد الحصول عليها لاحظ وجود الحقل المحسوب EndDate الذي يتم حساب قيمته من الحقول المعادة من الاستعلام باستخدام الوظيفة DateAdd التي تضيف فترة زمنية معينة حسب المحددات الممررة لها إلى تاريخ ممرر لها وتعيد قيمة التاريخ الجديد وتعاد قيمته مع قائمة الحقول التي يعيدها الاستعلام وبعد الاستعلام نتأكد من أنه قد جلب نتائج فعلا بالتحقق من قيمة الخاصية Count ثم نستدعي الوظيفة DisplayWaeaaCalcs للقيام بالحسابات وإظهار النتائج

2

 وممّا زادنـــي شرفــاً وتيهــاً   **  وكدت بأخمصي أطأ الثريّا

دخولي تحت قولك يا عبادي  **   وأن صيّرت أحمد لي نبيّـاً

#4

شغل البرنامج ولاحظ ظهور قيم الاحتسابات في مربعات النصوص عند التنقل في كلا شبكتي البيانات إذا كانت لديك بيانات قمت بحفظها كما طلبت منك سابقا

post-207223-12704483594819_thumb.jpg

من أجل إظهار الودائع التي تبدأ بتاريخ معين وإظهارها أضف نموذج آخر للمشروع باسم Form2 ثم أضف DataGridView له واضبط الخاصية Dock للقيمة Fill لجعل شبكة البيانات تملأ كامل مساحة النموذج ثم نسق النموذج بحيث يكون كبيرا كفاية لعرض البيانات الناتجة عن الاستعلام

post-207223-1270448375386_thumb.jpg

أضف زرا للنموذج From1 واجعل إجراء معالجة حدث النقر عليه يماثل الكود التالي

        private void Button1_Click(object sender, EventArgs e)
        {
            System.DateTime d = Convert.ToDateTime(Interaction.InputBox("Enter Date", "Title", "DefaultResponse", 100, 200));
            var Dawa = from a in myDataSet.Wadaeaa
                       join B in myDataSet.Customers on
                       a.CustomerID equals B.ID
                       where a.StartDate == d
                       select new
                       {
                           B.CustomerName,
                           B.CurrentAccountNumber,
                           a.WadeaaNumber,
                           a.WadeaaAmount,
                           a.WadeeaPeriod,
                           a.StartDate,
                           EndDate = DateAndTime.DateAdd(DateInterval.Month, a.WadeeaPeriod, a.StartDate)
                       };

            Form2 c = new Form2();
            c.DataGridView1.DataSource = Dawa.ToList();
            c.DataGridView1.Update();
            c.ShowDialog();
        }

لاحظ أنني استخدمت ميزة في فيجول ستوديو تمكنني من حذف محددات إجراء معالجة حدث ما إن كنت على يقين أنني لن أحتاج لاستخدامها

في جملة الاستعلام تلاحظ أنني استخدمت Join للربط بين الجداول عند عملية الاستعلام كي نتجنب مشكلة ظهور بيانات مكررة من أحد الجداول من أجل جميع سطور الجدول الآخر حيث استخدمنا نفس أسلوب العلاقة التي قمنا بإنشائها في البداية بين الجدولين من حيث ربط الحقل CustomerID في الجدول Wadaeaa بالحقل ID في الجدول Customer و استخدمنا في قسم Where شرط لتصفية نتائج الاستعلام بحيث نحصل على الودائع التي تبدأ بتاريخ معين ثم نستخدم عبارة Select لتحديد الحقول التي نريد إظهارها كنتائج الاستعلام

ومن أجل إظهار النتائج في Form2 قمنا بإنشاء متغير من نوع تلك النافذة ثم ضبطنا قيمة DataSource لشبكة البيانات الموجودة على ذلك النموذج إلى النتيجة المعادة من الاستعلام مستخدمين الطريقة ToList لتحويل النتائج إلى شكل يمكن إظهاره في شبكة البيانات

ومن أجل الحصول على الودائع التي تنتهي بتاريخ معين يمكننا استخدام نفس الكود السابق بعد تعديل بسيط في قسم Where بحيث يصبح الكود كما يلي

        private void Button2_Click(object sender, EventArgs e)
        {
            DateTime d = Convert.ToDateTime(Interaction.InputBox("Enter Date", "Title", "DefaultResponse", 100, 200));
            var Dawa = from a in myDataSet.Wadaeaa
                       join B in myDataSet.Customers on
                       a.CustomerID equals B.ID
                       where DateAndTime.DateAdd(DateInterval.Month, a.WadeeaPeriod, a.StartDate) == d
                       select new
                       {
                           B.CustomerName,
                           B.CurrentAccountNumber,
                           a.WadeaaNumber,
                           a.WadeaaAmount,
                           a.WadeeaPeriod,
                           a.StartDate,
                           EndDate = DateAndTime.DateAdd(DateInterval.Month, a.WadeeaPeriod, a.StartDate)
                       };

            Form2 c = new Form2();
            c.DataGridView1.DataSource = Dawa.ToList();
            c.DataGridView1.Update();
            c.ShowDialog();

        }
2

 وممّا زادنـــي شرفــاً وتيهــاً   **  وكدت بأخمصي أطأ الثريّا

دخولي تحت قولك يا عبادي  **   وأن صيّرت أحمد لي نبيّـاً

#5

مشكور على النقل مع ذكر المصدر

بالتوفيق إن شاء الله

عن عائشة رضي الله عنها أن النبي صلى الله عليه وسلم قال: إن الله يحب إذا عمل أحدكم عملا أن يتقنه

نعيب زماننا والعيب فينا ... وما لزماننا عيب سوانا

ونهجو ذا الزمان بغير ذنب ... ولو نطق الزمان لنا هجانا

محمد سامر أبو سلو

#6

صورة البرنامج النهائيه

والسورس كود فى المرفقات

post-207223-12706754613014_thumb.jpg

LinqToDataSet.zip

1

 وممّا زادنـــي شرفــاً وتيهــاً   **  وكدت بأخمصي أطأ الثريّا

دخولي تحت قولك يا عبادي  **   وأن صيّرت أحمد لي نبيّـاً

#7

الله يجزاك بالخير

#8

جزاكم الله خيرا

كم كنت اتمنى ان يكون هناك شرح اكثر

ان صنائع المعروف تقى مصارع السوء

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

تُغفر بها الذنوب وتُقضى بها الحوائج وتُفرًّج بها الهموم.

اللهم صلى على سيدنا محمد وعلى اهله واصحابه اجمعيـــن

-------------------------------------------------------------------------------------------

#9

ممتاز أخي والله مجهود جبار

+1 +1 +1 +1 +1

#10

السلام عليكم

شكراً جزيلاً لهذا المثال

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

آملاً المساعدة

مع فائق الشكر والاحترام

الكود

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.VisualBasic;


namespace DataSetXML
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                myDataSet.Clear();
                myDataSet.ReadXml(@"c:\TestData.xml");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }


        private void customerBindingNavigatorSaveItem_Click(object sender, EventArgs e)
        {
            try 
            {
                myDataSet.WriteXml(@"c:\TestData.xml");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void customerBindingNavigator_RefreshItems(object sender, EventArgs e)
        {

        }

        private void customerDataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
        { 
        }


        }
    }
#11

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

اخي اذا كان مسار وصياغة الملف سليمة 100% سيتم تحميل بياناته في الـ DataSet, ولكن انصحك باستخدام LINQ to XML

1

.:: Wish to become better and better ::.

#12
VB Helper كتب:

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

اخي اذا كان مسار وصياغة الملف سليمة 100% سيتم تحميل بياناته في الـ DataSet, ولكن انصحك باستخدام LINQ to XML

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

أخي العزيز مشكور للمساعدة ، لكن عذراً فلم أفهم معنى استخدام (Linq to Xml) ، وطريقة عمل ذلك .

code.txt

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