ما هو الجانب الأصعب أو الأكثر سوء فهم في LINQ؟[مغلق]

StackOverflow https://stackoverflow.com/questions/215548

  •  03-07-2019
  •  | 
  •  

سؤال

خلفية:خلال الشهر المقبل، سألقي ثلاث محادثات حول أو على الأقل بما في ذلك LINQ في سياق C#.أود أن أعرف ما هي المواضيع التي تستحق الاهتمام بها بقدر لا بأس به، استنادًا إلى ما قد يجد الناس صعوبة في فهمه، أو ما قد يكون لديهم انطباع خاطئ عنه.لن أتحدث عنه على وجه التحديد LINQ ل SQL أو Entity Framework باستثناء أمثلة لكيفية تنفيذ الاستعلامات عن بعد باستخدام أشجار التعبير (وعادةً IQueryable).

إذن، ما الذي وجدته صعبًا؟ LINQ؟ماذا رأيت من حيث سوء الفهم؟قد تكون الأمثلة أيًا مما يلي، ولكن من فضلك لا تقيد نفسك!

  • كيف ال C# يعامل المترجم تعبيرات الاستعلام
  • تعبيرات لامدا
  • أشجار التعبير
  • طرق التمديد
  • أنواع مجهولة
  • IQueryable
  • المؤجل مقابل التنفيذ الفوري
  • البث مقابل التنفيذ المخزن (على سبيل المثالتم تأجيل OrderBy ولكن تم تخزينه مؤقتًا)
  • المتغيرات المحلية المكتوبة ضمنيًا
  • قراءة التوقيعات العامة المعقدة (على سبيل المثال. لا يحصى.انضم)
هل كانت مفيدة؟

المحلول

تأخر التنفيذ

نصائح أخرى

أعرف أن مفهوم التنفيذ المؤجل يجب أن يكون مفهوماً بالنسبة لي الآن، ولكن هذا المثال ساعدني حقاً في الحصول على فهم عملي له:

static void Linq_Deferred_Execution_Demo()
{
    List<String> items = new List<string> { "Bob", "Alice", "Trent" };

    var results = from s in items select s;

    Console.WriteLine("Before add:");
    foreach (var result in results)
    {
        Console.WriteLine(result);
    }

    items.Add("Mallory");

    //
    //  Enumerating the results again will return the new item, even
    //  though we did not re-assign the Linq expression to it!
    //

    Console.WriteLine("\nAfter add:");
    foreach (var result in results)
    {
        Console.WriteLine(result);
    }
}

يُرجع الكود أعلاه ما يلي:

Before add:
Bob
Alice
Trent

After add:
Bob
Alice
Trent
Mallory

أن هناك أكثر من مجرد LINQ ل SQL والميزات أكثر من مجرد SQL محلل مضمن في اللغة.

تدوين O الكبير.يجعل LINQ من السهل جدًا كتابة خوارزميات O(n^4) دون أن تدرك ذلك، إذا كنت لا تعرف ما تفعله.

أعتقد أن حقيقة أ Lambda يمكن أن يحل التعبير لكل من شجرة التعبير والمفوض المجهول، حتى تتمكن من تمرير نفس التصريح lambda التعبير لكليهما IEnumerable<T> طرق التمديد و IQueryable<T> طرق التمديد.

أخذني طريق وقتًا طويلاً جدًا لإدراك أن العديد من طرق امتداد LINQ مثل Single(), SingleOrDefault() وما إلى ذلك لديها حمولات زائدة تأخذ لامدا.

يمكنك ان تفعل :

Single(x => x.id == id)

ولست بحاجة إلى قول هذا - وهو الأمر الذي جعلني أقوم به من خلال بعض البرامج التعليمية السيئة

Where(x => x.id == id).Single()

في LINQ إلى SQL، أرى باستمرار أشخاصًا لا يفهمون DataContext، وكيف يمكن استخدامه وكيف ينبغي استخدامه.الكثير من الأشخاص لا يرون DataContext على حقيقته، فهو كائن وحدة عمل، وليس كائنًا ثابتًا.

لقد رأيت مرات عديدة حيث يحاول الأشخاص تخصيص DataContext/الجلسة/إلخ بدلاً من تحديد وقت جديد لكل عملية.

وبعد ذلك يتم التخلص من DataContext قبل تقييم IQueryable ولكن هذا أكثر فائدة للأشخاص الذين لا يفهمون IQueryable من DataContext.

المفهوم الآخر الذي أرى الكثير من الالتباس معه هو Query Syntax vs Expression Syntax.سأستخدم أيهما أسهل في هذه المرحلة، وغالبًا ما ألتزم بصيغة التعبير.لا يزال الكثير من الأشخاص لا يدركون أنهم سينتجون نفس الشيء في النهاية، حيث يتم تجميع الاستعلام في التعبير بعد كل شيء.

أظن ال الجزء الذي يساء فهمه من LINQ هو أنه ملف امتداد اللغة, ، وليس امتدادًا أو إنشاءًا لقاعدة البيانات.

LINQ هو أكثر بكثير من LINQ to SQL.

الآن بعد أن استخدم معظمنا LINQ على المجموعات، لن نعود مرة أخرى!

LINQ هي الميزة الوحيدة الأكثر أهمية لـ .NET منذ الإصدارات العامة في الإصدار 2.0 والأنواع المجهولة في الإصدار 3.0.

والآن بعد أن أصبح لدينا Lambda، لا أستطيع انتظار البرمجة الموازية!

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

أنا جديد إلى حد ما على LINQ.إليك الأشياء التي تعثرت فيها في محاولتي الأولى

  • الجمع بين عدة استعلامات في واحد
  • تصحيح أخطاء استعلامات LINQ بشكل فعال في Visual Studio.

الشيء الذي لم أدركه في الأصل هو أن بناء جملة LINQ لا يتطلب IEnumerable<T> أو IQueryable<T> للعمل، LINQ يتعلق فقط بمطابقة الأنماط.

نص بديل http://bartdesmet.info/images_wlw/QIsIQueryabletheRightChoiceforMe_13478/image_thumb_3.png

هنا هو الجواب (لا، ​​أنا لم يفعل ذلك اكتب تلك المدونة، كما فعل بارت دي سميت، وهو أحد أفضل المدونين الذين وجدتهم على LINQ).

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

فهم متى يتسرب التجريد بين موفري Linq.تعمل بعض الأشياء على الكائنات وليس على SQL (على سبيل المثال، .TakeWhile).يمكن ترجمة بعض الأساليب إلى SQL (ToUpper) بينما لا يمكن للآخرين ذلك.تكون بعض التقنيات أكثر كفاءة في الكائنات حيث يكون البعض الآخر أكثر فعالية في SQL (طرق ربط مختلفة).

زوجان من الأشياء.

  1. الناس يفكرون في Linq مثل Linq إلى SQL.
  2. يعتقد بعض الأشخاص أنه يمكنهم البدء في استبدال كل foreach/logic باستعلامات Linq دون مراعاة الآثار المترتبة على الأداء.

حسنًا، نظرًا للطلب، قمت بكتابة بعض عناصر التعبير.لست سعيدًا بنسبة 100% بكيفية تآمر المدون وLiveWriter لتنسيقه، لكن الأمر سيفي بالغرض الآن...

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

ها هو, ، أحبه أو اكرهه...

قد تكون بعض رسائل الخطأ، خاصة من LINQ إلى SQL، مربكة جدًا. ابتسامة

لقد عضني الإعدام المؤجل عدة مرات مثل أي شخص آخر.أعتقد أن الشيء الأكثر إرباكًا بالنسبة لي هو موفر استعلام SQL Server وما يمكنك فعله وما لا يمكنك فعله به.

ما زلت مندهشًا من حقيقة أنه لا يمكنك إجراء Sum() على عمود عشري/نقود يكون فارغًا في بعض الأحيان.لن ينجح استخدام DefaultIfEmpty().:(

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

أن IQueryable يقبل كليهما، Expression<Func<T1, T2, T3, ...>> و Func<T1, T2, T3, ...>, ، دون إعطاء تلميح حول تدهور الأداء في الحالة الثانية.

إليك مثال التعليمات البرمجية الذي يوضح ما أعنيه:

[TestMethod]
public void QueryComplexityTest()
{
    var users = _dataContext.Users;

    Func<User, bool>                funcSelector =       q => q.UserName.StartsWith("Test");
    Expression<Func<User, bool>>    expressionSelector = q => q.UserName.StartsWith("Test");

    // Returns IEnumerable, and do filtering of data on client-side
    IQueryable<User> func = users.Where(funcSelector).AsQueryable();
    // Returns IQuerible and do filtering of data on server side
    // SELECT ... FROM [dbo].[User] AS [t0] WHERE [t0].[user_name] LIKE @p0
    IQueryable<User> exp = users.Where(expressionSelector);
}

لا أعرف إذا كان هذا بمثابة سوء فهم - ولكن بالنسبة لي، ببساطة غير معروف.

لقد سررت بمعرفة المزيد عن DataLoadOptions وكيف يمكنني التحكم في الجداول التي يتم ضمها عند إجراء استعلام معين.

انظر هنا لمزيد من المعلومات: شبكة MSDN:خيارات تحميل البيانات

أود أن أقول إن الجانب الأكثر سوء الفهم (أو هل ينبغي عدم فهم ذلك؟) في LINQ هو IQueryable و موفرو LINQ المخصصون.

أنا أستخدم LINQ منذ فترة وأنا مرتاح تمامًا في عالم IEnumerable، ويمكنني حل معظم المشكلات باستخدام LINQ.

ولكن عندما بدأت في النظر والقراءة عن IQueryable، والتعبيرات وموفري linq المخصصين، أثار ذلك يدور في ذهني.ألقِ نظرة على كيفية عمل LINQ to SQL إذا كنت تريد رؤية بعض المنطق المعقد جدًا.

وإنني أتطلع إلى فهم هذا الجانب من LINQ ...

كما قال معظم الناس، أعتقد أن الجزء الأكثر سوء فهم هو افتراض أن LINQ هو مجرد بديل لـ T-SQL.مديري الذي يعتبر نفسه بصفته خبيرًا في TSQL لن يسمح لنا باستخدام LINQ في مشروعنا بل ويكره MS لإطلاقه مثل هذا الشيء!!!

ماذا يمثل var عند تنفيذ الاستعلام؟

فعلا iQueryable, iSingleResult, iMultipleResult, أم أنه يتغير بناءً على التنفيذ.هناك بعض التكهنات حول استخدام (ما يبدو أنه) الكتابة الديناميكية مقابل الكتابة الثابتة القياسية في C#.

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

على سبيل المثال:

from outerloopitem in outerloopitems
from innerloopitem in outerloopitem.childitems
select outerloopitem, innerloopitem

group by لا يزال يجعل رأسي تدور.

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

الاستعلامات المجمعة

حقيقة أنه لا يمكنك السلسلة IQueryable لأنها استدعاءات الأسلوب (بينما ما زال لا شيء آخر سوى SQL قابل للترجمة!) وأنه يكاد يكون من المستحيل التغلب عليه أمر محير للعقل ويخلق انتهاكًا كبيرًا لـ DRY.انا بحاجة الى بلدي IQueryable's المخصصة التي لا أمتلك فيها استعلامات مجمعة (لقد قمت فقط بتجميع استعلامات للسيناريوهات الثقيلة)، ولكن في الاستعلامات المجمعة لا يمكنني استخدامها وأحتاج بدلاً من ذلك إلى كتابة بناء جملة استعلام عادي مرة أخرى.الآن أقوم بنفس الاستعلامات الفرعية في مكانين، وأحتاج إلى تذكر تحديث كليهما إذا تغير شيء ما، وما إلى ذلك.كابوس.

أعتقد أن المفهوم الخاطئ رقم 1 حول LINQ to SQL هو أنه لا يزال يتعين عليك معرفة SQL من أجل الاستفادة منه بشكل فعال.

شيء آخر يساء فهمه حول Linq to Sql هو أنه لا يزال يتعين عليك خفض أمان قاعدة البيانات الخاصة بك إلى حد السخافة حتى تتمكن من العمل.

النقطة الثالثة هي أن استخدام Linq to Sql مع الفئات الديناميكية (بمعنى أن تعريف الفئة يتم إنشاؤه في وقت التشغيل) يؤدي إلى قدر هائل من التجميع في الوقت المناسب.الأمر الذي يمكن أن يقتل الأداء تمامًا.

تحميل كسول.

كما ذكرنا، التحميل البطيء والتنفيذ المؤجل

كيف يختلف LINQ إلى الكائنات وLINQ إلى XML (IEnumerable) عن LINQ إلى SQL(IQueryable)

كيف لبناء طبقة الوصول إلى البيانات، وطبقة الأعمال، وطبقة العرض مع LINQ في جميع الطبقات.... ومثال جيد.

كما قال معظم الناس، أعتقد أن الجزء الأكثر سوء فهم هو افتراض أن LINQ هو مجرد بديل لـ T-SQL.مديري الذي يعتبر نفسه خبيرًا في TSQL لن يسمح لنا باستخدام LINQ في مشروعنا بل ويكره MS لإطلاقه مثل هذا الشيء!!!

المعاملات (بدون استخدام TransactionScope)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top