الرئيسية > ado.net entity framework > الباب الثالث : الاستعلام في نتائج كتل البيانات

الباب الثالث : الاستعلام في نتائج كتل البيانات

في هذا الباب ، سنتناول كيفية كتابة استعلامات Queries للاستعلام عن البيانات بطريقتين : مزود LINQ to Entities و ما يعرف بـ Entity SQL . بالاضافة الى كل هذا ، سنتناول الاستعلامات من جانب اخر وهو الاستعلامات المبنية على الطرق Method Based Queries وكذلك باني الاستعلامات الموجود في EF . وبذلك سيكون لديك فكرة عامة حول مختلف الطرق المستخدمة في الاستعلام عن البيانات .

1 – استعلام نموذج وكائنات بدلا من قاعدة بيانات !

اذا كنت قد اعتدت على ارسال استعلامات إلى قاعدة البيانات مباشرة ، فهنا الوضع يختلف ، فأنت كمبرمج او مطور ليس عليك ان ترى قاعدة البيانات بأي شكل من الاشكال ، وانما انت تتعامل مع نكب EDM فقط ، وتستعلم عن البيانات الموجودة فيه هو لا في قاعدة البيانات ! هذا الامر ليس بالصعوبة التي تعتقدها وذلك بفضل التقنيات المتوفرة للإستعلام والتي تسهل العمل كثيرا ولن تكون كما يتوقعها البعض ، فنحن في الأساس لا نقوم بأمور معقده وانما اطار العمل EF يقوم بها ونحن نوجه له الاوامر فقط لا اكثر .

بمجرد الاستعلام عن البيانات ، يقوم اطار العمل باستخدام البنية التحتية المتوفرة في تقنية ADO.NET والتي ستتمثل في SQLClient مثلا ، ويقوم بتحويل الاستعلام المرسل اليه إلى استعلام مناسب لذلك المزود بالطبع ، وبمجرد حصوله على البيانات ، يقوم بتحويلها مجددا إلى كائنات ، لذلك نحن لا نرى بيانات طرية وانما نرى بيانات مغلفة ككائنات .

2- بناء أول استعلام :

هنا سنبدأ بكتابة استعلام بسيط جدا ، لا يحتوي على ايه شروط مركبة او أي تجميعات او خلافه ، قم باعداد ملف Model جديد في مشروع جديد، واختر الجداول الثلاثة Orders,OrderDetails,Products واضفها اليه ، وسمه NORTHWINDmodel ثم توجه إلى أي نافذة Windows Form واضف اداة DataGridView – هذه العملية طبقها في كل مرة حتى نصل إلى الباب السابع : استخدام ربط البيانات Data Binding مع Windows Forms,WPF – وتوجه إلى حدث التحميل للنافذة واكتب الكود التالي :

   1: Dim OrderEntities As New NORTHWNDEntities

   2:  

   3: Dim myOrder = From order In OrderEntities.Orders _

   4:               Select order.OrderID, order.OrderDate, _

   5:               order.RequiredDate()

   6:  

   7: Me.DataGridView1.DataSource = myOrder

قم بتشغيل البرنامج لتظهر امامك النتيجة التالية :

هنا قد تظهر أهمية النمذجة Modeling للبيانات على هيئة فئات وكائنات ، حيث اننا نصبح قادرين على التعامل مع فئات وكائنات منها تستخدم بشكل مباشر ، وتقدم لنا تقنية IntelliSence من Visual Studio الدعم اللازم للقيام بهذا الامر اما LINQ فتقول لنا : ودعوا ايام T-SQL !

 

3- استعلامات LINQtoEntities :

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

تعتبر استعلامات LINQ to Entities اسهل من حيث البنية اللغوية Syntax عن الاستعلامات الاخرى التي سنعرفها لاحقا ، حيث ان استعلامات LINQ اصبحت تستخدم في كثير من المجالات كـ LINQtoSQL,LINQtoDataset,LINQtoXML وغيرها .

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

   1: Dim OrderEntities As New NORTHWNDEntities

   2:  

   3: Dim myOrder = From order In OrderEntities.Orders _

   4:               Select order.OrderID, order.OrderDate, _

   5:               order.RequiredDate()

   6:  

   7: Me.DataGridView1.DataSource = myOrder

الكائن myOrder هو من النوع System.LINQ.IQueryable بينما القيمة التي يعود بها وقت التنفيذ هي من النوع System.Data.Objects.ObjectQuery ، فاستعلامات LINQ تعيد كائنات من النوع IQueryable ،ولكن ولأن الاستعلام منفذ على كائنات تطبق اطار العمل EF ، فإن المترجم سيقوم بتحويلها إلى النوع ObjectQuery.

بالنسبة للواجهة IQueryable والتي تتبع فضاء الاسماء system.LINQ فهي واجهة تمكن الفئة التي تطبقها من تنفيذ الاستعلامات عليها بتقنية LINQ وتحتوي على ثلاث خصائص وهي ElementType,Expression,Provider و طريقة واحدة وهي GetEnumerator ، بينما الفئة ObjectQuery هي فئة تطبق الواجهة IQueryable وتحمل طرق وخصائص اضافية عن تلك الموجودة في الواجهة IQueryable .

ويجب ان لا تغفل ان الكائن order داخل الاستعلام السابق ، هو من النوع Orders ، وفي المستقبل القريب سنعمل على هذه الملاحظه فلا تنساها حاليا .

4- استعلامات LINQ SQL التي تعيد كائنات :

في الجزء السابق ، قلنا بأن استعلامات LINQ to Entities تولد كائن من النوع ObjectQuery ، لكن في الحقيقة ، يوجد طريقة اخرى لإنشاء كائنات من النوع ObjectQuery مباشرة ، وفي هذه الطريقة نستخدم جمل استعلام جديدة تدعى Entity SQL ، وهي شبيهه بـ T-SQL المعروفة لكن مع بعض الاختلافات نوعا ما .

انشاء كائن QueryObject مباشرة تتم باستدعاء الطريقة CreateQuery التابعة لكائن الـ ObjectContext ونمرر لها الكتلة entity المراد الاستعلام فيها وكذلك نمرر لها جملة الاستعلام المطلوب تنفيذها ، الكود التالي مثال على ذلك :

   1: Dim OrderEntities As New NORTHWNDEntities

   2:  

   3: Dim QueryExpression As String = "SELECT VALUE o " & _

   4:                 " FROM NORTHWNDEntities.Orders AS o " & _

   5:                 " WHERE o.Freight > 20"

   6:  

   7: Dim myOrders = OrderEntities.CreateQuery(Of Orders) _

   8:                                     (QueryExpression)

   9:  

  10: Me.DataGridView1.DataSource = myOrders

وذلك الاستعلام بالضبط هو مثل استعلام LINQ التالي :

   1: Dim myOrders = From order In OrderEntities.Orders _

   2:              Where order.Freight > 20 _

   3:              Select order

الكائن myOrders في الاول هو من النوع ObjectQuery ، وهكذا نكون قد نجحنا في انشاء استعلام مباشرة من النوع ObjectQuery . ولكن السؤال الذي يطرح نفسه الآن والذي يتبادر بقوة إلينا الآن : لماذا قد نحتاج إلى استخدام هذا النوع من الاستعلامات والخير والبركة في LINQ to Entities التي اراحتنا من مشاكل التنصيص والاخطاء الاملائية واخطاء وقت التنفيذ والباراميترات وغيرها من المشاكل الكثيرة جدا ؟

حسنا، حتى الآن لا يمكنني ان اقول لك سوى اننا نستخدم هذه الطريقة من اجل الحصول على كائن ObjectQuery مباشرة للاستفادة من الطرق التي توجد في هذا النوع من الكائنات ولا توجد في أي كائن من النوع IQueryable وقت التصميم Design Time ، لذلك اتمنى منك التفريق بين الاثنين .

وفي الحقيقة ، كانت Entity SQL الطريقة الاولى والاساسية المعتمدة في الاستعلام في اطار العمل EF ذلك لأن تقنية LINQ كانت هي الاخرى تحت التطوير في الوقت ذاته .

4-1 : بنية استعلامات Entity SQL :

يجب علينا ان نتعرف على بنية استعلامات Entity SQL والصورة العامة لها ، وهي بشكل عام تتبع الصورة التالية :

   1: SELECT VALUE c FROM ContextObject.EntityClient AS c

بالنسبة للكلمة المحجوزة Keyword المدعوة VALUE فهي تستخدم فقط اذا كنت تود تحديد عنصر واحد فقط ، والذي قد يكون كتلة بيانات Entity ، خاصية Property او حتى Entity Collection كما بالمثالين التاليين:

 

   1: SELECT VALUE c FROM NorthwindEntities.Orders AS c

   2: SELECT VALUE c.OrderID FROM NorthwindEntities.Orders AS c

ففي المثالين السابقين اخترنا قيمة واحدة وهي c و c.OrderID ، وفي حالة رغبتنا بتحديد اكثر من عنصر واحد فعليك ان لا تكتب الكلمة المحجوزة VALUE كما بالمثالين التاليين :

   1: SELECT c, c.OrderID FROM NorthwindEntities.Orders AS c

   2: SELECT c.OrderID,c.RequiredDate FROM NorthwindEntities.Orders AS c

وخذ حذرك جيدا ، فلو تجرأت على نسيان استخدام الكلمة المحجوزة VALUE بينما انت تحدد قيمة واحدة فقط كما بالمثالين الاولين ، فإن استثناء Exception من النوع InvalidOperationException سيتم القاؤه في وجهك وقت التنفيذ ، أما ان كتبت الكلمة المحجوزة VALUE بينما انت تحدد اكثر من قيمة في جملة الاستعلام ، فإن استثناء من نوع EntitySQLException ، فانتبه جيدا ولا تقل النبهاني لم يخبرني بذلك !

وبالنسبة للشروط ، فالكلمة المحجوزة WHERE تستخدم بالضبط مثل T-SQL :

 

   1: SELECT c.OrderID,c.RequiredDate FROM NorthwindEntities.Orders AS c WHERE c.Frieght > 20

4-4 : استخدام الباراميترات Parameters في Entity SQL :

من ميزات الفئة ObjectQuery دعمها للباراميترات ايضا ، استخدام الباراميترات في كائن من هذه الفئة ليس مختلفا عن المألوف المعهود في فئات كـ XXXCommand التابعة لمكتبة ADO.NET . ولتعيين كلمه كباراميتر يجب ان يبدأ اسمه بالرمز @ .

ما سيختلف هذه المرة ، أنه يتوجب عليك انشاء كائن ObjectQuery جديد بدلا عن الطريقة CreateQuery التابعة للفئة Objectcontext . هذا مثال على ذلك :

   1: Dim OrderEntities As New NORTHWNDEntities

   2:  

   3: Dim QueryExpression As String = " SELECT c.OrderID,c.RequiredDate " & _

   4:                                 " FROM NorthwindEntities.Orsder AS c " & _

   5:                                 " WHERE c.Frieght > @Frieght "

   6:  

   7: Dim myOrders As New ObjectQuery(Of Orders)(QueryExpression, OrderEntities)

   8:  

   9: myOrders.Parameters.Add(New ObjectParameter("@Frieght", 20))

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

 

   1: Dim OrderEntities As New NORTHWNDEntities

   2:  

   3: Dim QueryExpression As String = " SELECT c.OrderID,c.RequiredDate " & _

   4:                                 " FROM NorthwindEntities.Orders AS c " & _

   5:                                 " WHERE @FieldNAme > @Value "

5- الاستعلامات المبنية على الطرق Method Based Queries :

بدون لف او دوران ، لن ارفع ضغطك بمقدمات المديح والهجاء المعتادة ، فالاستعلامات المبنية على الطرق تساعدك في التخلص من المصاعب التي قد تواجهك في استخدام Entity SQL ، فهي تقوم بتوليد جمل الاستعلام بدلا عنك !

واذا كان السؤال : لماذا استخدم Entity SQL بينما السهولة تكمن في استخدام LINQ to Entities ، اجيبك ان لغات الدوت نت بما فيها VB.NET و C# تدعمان LINQ وتفهمانها، بينما CLR لا ، وهي الام والأساس في اطار العمل .Net Framework، لذلك فتنفيذ LINQ سيكون ابطأ طبعا، وسنتعرف في مستقبل صفحات هذا الكتاب ، أن استخدام EntitySQL مع الكائن ObjectQuery هو اسرع بنسبة 24% من LINQ to Entities .

سأحاول التوضيح اكثر في هذه النقطة ببيان امر مهم عن الاستعلام بصيغة LINQ ، وهي ان معالج استعلامات LINQ تتم من خلال ترجمه ذلك إلى الاستعلام إلى مجموعة من الطرق Methods التي تنفذ على الكائنات المستعلمة ، فالكلمات المحجوزة كـ WHERE,SELECT وغيرها لها طرق مقابلة لها يتم ترجمتها اليها .

وعملية استخدام الطرق مباشرة بدل جمل LINQ لا يعيبها شيء ، سوى انها تفتقد إلى ميزتان مهمتان في LINQ وهما : سهولة الكتابة ، وسهولة القراءة .

واكاد اجزم بدرجه كبيرة جدا ، انك قد اصبحت متلهفا للتعرف على كيفية الاستعلام بالطرق بدلا من جمل الاستعلام المعتادة ، لكن يجب ان يكون لديك خلفية عن ميزة جديدة ظهرت في النسخة 9 من VB و 3 من C# وهي تعبيرات لامدا Lambda Expressions . اعرف ان هناك الكثيرين الان ممن سيتخوفون من هذا الموضوع وقد يفكرون بترك فكرة الاستعلام بالطرق من البداية ، ولكن مهلا فتعبيرات لامدا ما هي الا دوال مصغرة تكتب في السطر مع باقي التعبيرات Expressions ، ولكي يزول عنك كل هذا الخوف والقلق ، انظر إلى الاستعلام التالي :

   1: Dim OrdersEntities As New NORTHWNDEntities

   2:  

   3: Dim myOrders = OrdersEntities.Orders _

   4:             .Where(Function(orders) orders.Freight > 20)

ما رأيك به ؟ أليس سهلا ؟ الاستعلام السابق ، سيعيد كل الكائنات التي تنطبق فيها الطريقة المكتوبة بين الحاصرتين ، فقيمة الخاصية Freight اكبر من 20 يعني تحقق الشرط .

ان كنت تريد كتابة الشرط السابق الممثل في تعبير لامدا بدالة كاملة منفصلة ، فإليك الدالة :

 

   1: Private Function IsFrieghtLargerthan20(ByVal order As Orders) As Orders

   2:     If order.Freight > 20 Then

   3:         Return order

   4:     Else

   5:         Return Nothing

   6:  

   7:     End If

   8: End Function

ما رأيك ؟ هل ترغب بكتابة تعبير لامدا ام دالة كاملة مكونه مما لا يقل عن 7 سطور مملة ولا داعي لها في حالات كهذه ؟

ما رأيك ان نحاول اضافة شيء جديد إلى الاستعلام السابق لتصبح الامور اكثر وضوحا ؟ فنلقم مثلا بترتيب الطلبات على حسب تاريخ الطلب OrderDate فسيكون لدينا شيء مثل الكود التالي :

 

   1: Dim myOrders = OrdersEntities.Orders _

   2:             .Where(Function(orders) orders.Freight > 20) _

   3:             .OrderBy(Function(o) o.OrderDate)

اعتقد ان الامور واضحة الآن اكثر من قبل ! وبالنسبة للكائن o فقد تعمدت تسميته بذلك الاسم حتى تتضح لك فكرة ان التعبير الثاني هو دالة لامدا منفصلة على السابقة !

العملية السابقة عندما قمنا بدمج اكثر من طريقة LINQ ، تسمى بالتقييد او التكبيل، حيث قمنا باستخدام اكثر من طريقة LINQ واحدة ، فكان لدينا طريقتان .

ولتتعرف على المزيد من الطرق الخاصة بـ LINQ ، فإذهب إلى مكتبة MSDN حيث تفصيل كل منها .

6- اقصر استعلام !

الفكرة من هذه الفقرة هو مراجعة ما سبق من خلال ذكر ملاحظة بسيطة ، وهي في ملف Model.Designer.vb – طبعا ملف Model.Designer.cs ايضا ! – لو عدت إلى حديثنا السابق عن ذلك الملف ومكوناته ، ستجد اننا قلنا في فئة الادارة ObjectContext ، ان ممثل الكتلة entity هو كائن من النوع ObjectQuery ، اذا نستنتج من هذا الكلام ان كل كتلة entity – كـ Orders مثلا- ما هي الا عبارة عن استعلام بالكائن ObjectQuery ، وبما اننا اعرفنا ان الكائن Objectquery يستخدم للاستعلام بواسطة استعلامات Entity SQL ، فإننا سنتوقع وجود صيغة مماثلة في حالتنا السابقة ؟

اذا عدنا إلى ملف الـ Model.Designer ستجد الكود التالي :

   1: Public ReadOnly Property Orders() As Global.System.Data.Objects.ObjectQuery(Of Orders)

   2:     Get

   3:         If (Me._Orders Is Nothing) Then

   4:             Me._Orders = MyBase.CreateQuery(Of Orders)("[Orders]")

   5:         End If

   6:         Return Me._Orders

   7:     End Get

   8: End Property

   9: Private _Orders As Global.System.Data.Objects.ObjectQuery(Of Orders)

نلاحظ من الكود السابق ، ان الكائن _Orders سيعود بقيمة استعلام بعد اسناد الصيغة [Orders] ، فلا نجد عبارة SELECT كما هي البداية المعتادة من جمل الاستعلام Entity SQL ، نتيجة السطور التسعة الماضية ، هي انه للحصول على الكتلة مباشرة ، يمكننا ايضا استخدام الكائن ObjectQuery وذلك بكتابة اسم الكتلة فقط .

7- استخدام EntityClient للإستعلام عن البيانات :

ربما تذكر كلامي السابق حول ان الاستعلام عن طريق EntityClient يعيد لنا البيانات بشكل مباشر، بمعنى آخر ، ستعود اليك البيانات على شكل جدول بحقول وسجلات عوضا عن التغليفه الكائنيه الجميلة ، لكن ما اعنيه بإعادتها للبيانات على شكل جدول بحقول وسجلات ، هو انها تعيد كائن من النوع EntityDataReader والذي هو مشتق من DBDatareader .

كائن قارئ البيانات EntityDataReader سيعيد لنا البيانات على شكل جدولي ، لكنه لا يحتوي فقط على قيمة البيانات كأنواع مباشرة String,Integer وغيرها ، وإنما يمكن ان تتضمن ايضا كائن من النوع DbDataReader او كائن DbDataRecord او حتى EntityKey .

فضاء الأسماء EntityClient يستخدم جمل استعلام Entity SQL – او كما يحلو للبعض تسميتها eSQL – ويحتوي ايضا داخله على فئات ، كفئة كائن اتصال EntityConnection ، كائن أوامر EntityCommand ، كائن باراميترات EntityParameter وحتى كائن تعارض EntityTransaction .

وحتى يزول الغموض عنك ، يجب ان نسوق مثالا كالتالي :

   1: 'انشاء كائن اتصال

   2: Using NthwndConnection As New  _

   3:                 EntityConnection("name=NORTHWNDEntities")

   4:     'eSQL جملة

   5:     Dim QueryExpression As String = _

   6:                 " SELECT c.OrderID,c.RequiredDate " & _

   7:                 " FROM NorthwindEntities.Orders AS c "

   8:  

   9:     Try

  10:         'فتح الاتصال

  11:         NthwndConnection.Open()

  12:  

  13:         'انشاء كائن اوامر من نوع

  14:         'ُEntityCommand

  15:  

  16:         Using NthwndCommand = _

  17:                         NthwndConnection.CreateCommand

  18:             'تمرير الاستعلام النصي الى كائن الاوامر

  19:             NthwndCommand.CommandText = QueryExpression

  20:  

  21:  

  22:             'انشاء كائن

  23:             'EntityDataReader

  24:             Using NthwndDataReader As EntityDataReader = _

  25:                         NthwndCommand.ExecuteReader _

  26:                         (CommandBehavior.SequentialAccess)

  27:  

  28:                 'هذا الجزء مخصص للقراءة

  29:                 Dim OrdersDataTable As DataTable = _

  30:                         NthwndDataReader.GetSchemaTable

  31:                 Dim i As Integer = 0

  32:  

  33:                 Do While NthwndDataReader.Read

  34:                     OrdersDataTable.Rows.Add _

  35:                         (NthwndDataReader.GetDataRecord(i))

  36:                     i += 1

  37:                 Loop

  38:  

  39:                 Me.DataGridView1.DataSource = OrdersDataTable

  40:             End Using

  41:  

  42:         End Using

  43:  

  44:  

  45:     Catch ex As Exception

  46:         MessageBox.Show(ex.Message)

  47:  

  48:     End Try

  49: End Using

لدي ملاحظات على الكود السابق اود اخبارك بها :

1- يجب ان تقوم باستيراد فضاء الاسماء System.Data.EntityClient

2- انا متأكد ان قراءة الكود السابق بالصورة الحالية صعبة وقد تصاب عينيك بالحول ، لذلك قم بنسخها إلى أي محرر نصوص برمجية ويفضل Visual Studio طبعا ، حتى تتمكن من القراءة بسلاسة.

3- تعمدت وضع تعليقات Comments داخل الكود حتى يسهل عليك تفهمها مباشرة خطوة بخطوة.

قد يرى بعض المبرمجون اننا ارتكبنا اثما وبهتانا عظيما ، حيث اننا دمرنا كل ما بنيناه في الفصول السابقة من تسهيل للعمل ، وعدنا إلى ايام انشاء الاتصالات والاوامر وقراءة السجلات سجل سجل واضافتها إلى اداة بشكل يدوي لا وبل فقدنا كل ما يخص النمذجة Modeling الخاصة بالبيانات ككائنات !

ويبدو ان الكود السابق في رأي مجموعة اخرى من المبرمجين يعود إلى ما قبل عصر EF ، مجموعة ثالثة من المبرمجين سيتركون هذه الفقرة مباشرة وسيكرهون شيء اسمه EntityClient وسيتجاهلون أي كود مشابه مستقبلا !

مجموعة رابعة من المبرمجين كانوا قد سمعوا من مكتبة MSDN بأن الاستعلام بهذه الطريقة هو ابطأ طرق الاستعلام في EF وبفارق كبير عن الطرق السابقة ، هنا اجدني اصرخ امامهم طالبا منهم الهدوء والتروي واعادة النظر جيدا في هذه الموضوع ، فليس من المعقول ان تقوم مايكروسوفت بصرف وقت وجهد ومال على تطوير طريقة لا فائدة منها واعداد طرق اخرى موازية لها عبثا ، وحيث انني من النوع الذي لا يحب السماع بالحل وقت وقوع الفأس بالرأس ؛ بل اتمنى ان يتمكن كل المبرمجون من معرفة كل الطرق والتقنيات الممكنة امامهم حتى يتمكنوا من حل الكثير من المشاكل بأفضل الطرق المتاحة ، حسنا دعني اخبرك شيئا ، قد نعود إلى هذا لاحقا !

8- الحصول على الاستعلام المرسل على قاعدة البيانات بصيغة T-SQL :

لترى الاستعلام النهائي الحقيقي المرسل إلى قاعدة البيانات ، يمكنك استخدام الاداة SQL Server Profiler في حالة كونك تستخدم قاعدة بيانات من نوع SQL Server ، ولكن يمكنك ايضا استخدام الطريقة ToTraceString التابعة للفئة ObjectQuery .

9- مشاكل الاستعلام !

لا تتوقع هنا ان احل مشكله قد صادفتك بخصوص السرعة او بخصوص المدعو الذي تكره اغلبيه المبرمجين حتى هذه السطور EntityClient ، ولكن يجب علينا الانتباه جيدا إلى أي جملة استعلام قد تنفيذها ، فقد لا تأت جملة الاستعلام بنفس النتيجة ، ففي هذا المثال :

 

   1: Dim myOrder = From order In OrderEntities.Orders _

   2:               Where order.ShipName.StartsWith("s") _

   3:               Select order.OrderID, order.OrderDate, _

   4:               order.RequiredDate()

تم استخدام الطريقة StartsWith التابعة للخاصية ShipName حيث أنها من النوع String ، وهذا الامر جميل جدا جدا جدا ، ولكن كيف سيتم توليد الاستعلام السابق بصيغه T-SQL وبالتالي ما هو الاستعلام الحقيقي الذي سيتم توليده على قاعدة البيانات ؟؟

سؤال وجيه حقا ، فالشرط في الكود السابق سينتج كما يلي :

   1: WHERE (CAST(CHARINDEX(N'S', [Extent1].[ ShipName]) AS int)) = 1

المشكلة التي تحصل هنا ، هي انه في SQL Server مثلا ، لا توجد الطريقة StartsWith وبالتالي سيتم تحويل الشرط إلى الذي رأيناه اولا وبالتالي فإن العملية ستطول ولو بنسبه بسيطة في نظر البعض ، لكن لمعلوماتك ، ففي الكود السابق تم استخدام الدالة CAST والتي لها تأثير سلبي على أداء قاعدة البيانات ، وهو ما يعرفه مديرو قواعد البيانات DBA’s جيدا ، واسألهم عن ذلك بنفسك !

لذلك سيكون من المفيد لو تتجنب دوال استعلامات مماثله بشكل مباشر ، وانما يفضل ان تقوم بالاستعلام السابق على نتيجة استعلام جاهزه !

 

بهذا نكون قد انتهينا من هذا الباب ، نلتقي قريبا ان شاء الله في الباب الرابع .

  1. فبراير 3, 2010 الساعة 11:20 ص

    مجهود رائع بارك الله فيك و أتمنى أن لك المزيد من التقدم

  2. محب سيدنا النبي
    فبراير 15, 2010 الساعة 12:01 م

    جزاك الله خيراً ، و ننتظر بقية الفصول إن شاء الله تعالى .

    بالنسبة لقسم : (4-1 : بنية استعلامات Entity SQL )
    فإن المثالين الرابع و الخامس منه لم يُنفذا و يظهر هذا الخطأ في وقت التنفيذ من النوع InvalidOperationException :

    The specified cast from a materialized ‘System.Data.Objects.MaterializedDataRecord’ type to the ‘EntityFramework.Orders’ type is not valid.

    • محب سيدنا النبي
      فبراير 15, 2010 الساعة 12:29 م

      و كذلك الحال في قسم (4-4 : استخدام الباراميترات Parameters في Entity SQL ) فإن المثال لا يعمل

      • محب سيدنا النبي
        فبراير 15, 2010 الساعة 1:48 م

        حيث يظهر الخطأ التالي عند جملة :
        myorder.Parameters.Add(New ObjectParameter(“@Frieght”, 20))

        The specified parameter name ‘@Frieght’ is not valid. Parameter names must begin with a letter and can only contain letters, numbers, and underscores. Parameter name: name

  3. محب سيدنا النبي
    فبراير 15, 2010 الساعة 2:29 م

    و في القسم (7- استخدام EntityClient للإستعلام عن البيانات ) يظهر هذا الخطأ في الجملة :
    Dim OrdersDataTable As DataTable = Northwind_DataReader.GetSchemaTable

    الخطأ كالتالي :
    The GetSchemaTable method is not supported.

  4. محب سيدنا النبي
    فبراير 15, 2010 الساعة 2:42 م

    ذكرتَ في القسم (8- الحصول على الاستعلام المرسل على قاعدة البيانات بصيغة T-SQL) التالي / “…يفضل ان تقوم بالاستعلام السابق على نتيجة استعلام جاهزه” ،

    و السؤال ماهي الطريقة باختصار ؟

  5. مارس 6, 2010 الساعة 10:20 ص

    اخي محب سيدنا النبي :

    بارك الله فيك على تجربتك للاكواد ، فالاخطاء يصعب علي اكتشافها بنفسي ! ان شاء الله سأقوم بتعديل الاكواد لحل المشاكل مع الرد على الاستفسارات الاخرى المتعلقه . وبالنسبه لسؤالك ، فجواب السؤال بشكل سريع هو ان تقوم بالاستعلام بشكل جامد rough اي بدون فرز او تصفيه ثم تقوم بعمل ما تشاء على ذات الاستعلام الناتج .

  1. No trackbacks yet.

أضف تعليقاً

إملأ الحقول أدناه بالمعلومات المناسبة أو إضغط على إحدى الأيقونات لتسجيل الدخول:

WordPress.com Logo

أنت تعلق بإستخدام حساب WordPress.com. تسجيل خروج   / تغيير )

صورة تويتر

أنت تعلق بإستخدام حساب Twitter. تسجيل خروج   / تغيير )

Facebook photo

أنت تعلق بإستخدام حساب Facebook. تسجيل خروج   / تغيير )

Google+ photo

أنت تعلق بإستخدام حساب Google+. تسجيل خروج   / تغيير )

Connecting to %s

%d مدونون معجبون بهذه: