דילוג לתוכן
  • דף הבית
  • קטגוריות
  • פוסטים אחרונים
  • משתמשים
  • חיפוש
  • חוקי הפורום
כיווץ
תחומים

תחומים - פורום חרדי מקצועי

💡 רוצה לזכור קריאת שמע בזמן? לחץ כאן!
  1. דף הבית
  2. תכנות
  3. ארכיון code613m
  4. EF - שאילתא על טבלת המבצעת קשר גומלין של רבים לרבים

EF - שאילתא על טבלת המבצעת קשר גומלין של רבים לרבים

מתוזמן נעוץ נעול הועבר ארכיון code613m
11 פוסטים 3 כותבים 557 צפיות
  • מהישן לחדש
  • מהחדש לישן
  • הכי הרבה הצבעות
התחברו כדי לפרסם תגובה
נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
  • רחמיםר מנותק
    רחמיםר מנותק
    רחמים מורחק
    כתב ב נערך לאחרונה על ידי
    #1

    דוגמא קלסית של מסד נתונים של בלוגים, לכל בלוג יכולים להיות כמה תגים, ולכל תג יכולים להיות שייכים כמה בלוגים, אז בקוד יוצרים רק מחלקה 'בלוג' עם מאפיין 'תגים' ומחלקה 'תג' עם מאפיין 'בלוגים' ו EF יוצר מאחורי הקלעים טבלה 'בלוג_תג' שבכל רשומה שלה יש מזהה בלוג ומזהה תג לאמר שבלוג זה מכיל תג זה ותג זה מכיל בלוג זה.
    עד כאן דברים ידועים, כעת השאלה איך אני יכול לעשות שאילתא על הטבלה הנסתרת הזאת?
    המטרה שלי היא לשלוף את כל הבלוגים שיש להם תג א' ותג ב' ואין להם תג ג' ותג ד'?
    אז אני יכול לגשת למאפיין 'תגים' שבמחלקת בלוג ולבדוק איזה תגים יש שם, אבל אז בא ה EF ורואה שאני ניגש למאפיין 'תגים' ומריץ שאילתא כדי למלאת לי את המערך של התגים, והוא עושה את זה כפול כל הבלוגים שהם כמה עשרות אלפים, וכך רצות עשרות אלפי שאילתות מיותרות לכאורא.
    לכן אני מחפש לעשות את זה כשאילתא יותר ישירה למסד נתונים בלי לגשת למאפיין 'תגים' אלא משהוא על הטבלה הנסתרת הזו.
    יש למישהו רעיון?

    אם הייתי רוצה לעשות את זה ישירות ב SQL הייתי כותב כך:

    SELECT * FROM Blogs
    WHERE Id IN (SELECT BlogId FROM Blogs_Tags WHERE TagId = 1 
                 INTERSECT
                 SELECT BlogId FROM Blogs_Tags WHERE TagId = 3
                 EXCEPT 
                 SELECT * FROM (SELECT BlogId FROM Blogs_Tags WHERE TagId = 2
                                INTERSECT
                                SELECT BlogId FROM Blogs_Tags WHERE TagId = 4))
    

    אבל כיון שאני עובד עם EF אני מחפש לעשות את זה בLINQ כמו שנוהגים ב EF, האם יש דרך?

    פורסם במקור בפורום CODE613 ב30/05/2017 15:10 (+03:00)

    תגובה 1 תגובה אחרונה
    0
    • dovidD מנותק
      dovidD מנותק
      dovid ניהול
      כתב ב נערך לאחרונה על ידי
      #2

      אתה טועה, הEF מבין אותך מצויין. כל עוד אינך מייצא את תוצאות השאילתה עד לביטויה המלא, הEF מתרגם מעולה שאילתות סבוכות מאוד.
      יש כמה אופנים לכתוב את מה שאתה רוצה, למשל:

      var blogsWith = db.Blogs.Where(x => x.Tags.Any(y => y.id == 1 || y.id == 3));
      var blogWithout = blogsWith.Where(x => !x.Tags.Any(y => y.id == 2 || y.id == 4));
      
      Console.WriteLine(blogWithout);
      

      אתה גם יכול לעשות את הטבלה של תג-בלוג למפורשת וככה לתשאל אותה ישירות.

      פורסם במקור בפורום CODE613 ב01/06/2017 00:12 (+03:00)

      מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

      בכל נושא אפשר ליצור קשר dovid@tchumim.com

      תגובה 1 תגובה אחרונה
      2
      • רחמיםר מנותק
        רחמיםר מנותק
        רחמים מורחק
        כתב ב נערך לאחרונה על ידי
        #3

        תודה דוד,
        עשית: y.id == 1 || y.id == 3
        כלומר או זה או זה, אבל אני צריך את הבלגים שיש להם גם תג 1 וגם תג 2, ואין להם גם תג 3 וגם תג 4
        איך עושים את זה?

        פורסם במקור בפורום CODE613 ב01/06/2017 08:55 (+03:00)

        תגובה 1 תגובה אחרונה
        0
        • א מנותק
          א מנותק
          אבי
          כתב ב נערך לאחרונה על ידי
          #4

          @רחמים

          איך עושים את זה?

          var blogs = db.Blogs.Where(x => x.Tags.Any(y => y.id == 1 && y.id == 3 && y.id != 2 && y.id != 4));
          

          פורסם במקור בפורום CODE613 ב01/06/2017 09:23 (+03:00)

          תגובה 1 תגובה אחרונה
          0
          • רחמיםר מנותק
            רחמיםר מנותק
            רחמים מורחק
            כתב ב נערך לאחרונה על ידי
            #5

            @אבי

            @רחמים
            איך עושים את זה?

            var blogs = db.Blogs.Where(x => x.Tags.Any(y => y.id == 1 && y.id == 3 && y.id != 2 && y.id != 4));
            

            ID לעולם לא יכול להיות שווה גם 1 וגם 3, אני צריך שיביא לי את כל הבלוגים, שבין התגים שלהם יש תג אחד עם מזהה 1 ותג אחרעם מזהה 3

            פורסם במקור בפורום CODE613 ב01/06/2017 09:26 (+03:00)

            תגובה 1 תגובה אחרונה
            0
            • dovidD מנותק
              dovidD מנותק
              dovid ניהול
              כתב ב נערך לאחרונה על ידי
              #6
              var blogsWith = db.Blogs.Where(x => x.Tags.Any(y => y.id == 1) &&
                     x.Tags.Any(y => || y.id == 3));
              

              פורסם במקור בפורום CODE613 ב01/06/2017 09:44 (+03:00)

              מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

              בכל נושא אפשר ליצור קשר dovid@tchumim.com

              תגובה 1 תגובה אחרונה
              2
              • רחמיםר מנותק
                רחמיםר מנותק
                רחמים מורחק
                כתב ב נערך לאחרונה על ידי
                #7

                תודה,

                איך באמת EF עובד, על פי איזה כללים? אני רוצה לדעת מראש אם ביטוי LINQ מסויים יהפך לשאילתא כמו שאני רוצה.

                פורסם במקור בפורום CODE613 ב01/06/2017 10:46 (+03:00)

                תגובה 1 תגובה אחרונה
                0
                • dovidD מנותק
                  dovidD מנותק
                  dovid ניהול
                  כתב ב נערך לאחרונה על ידי
                  #8

                  @רחמים

                  תודה,

                  איך באמת EF עובד, על פי איזה כללים? אני רוצה לדעת מראש אם ביטוי LINQ מסויים יהפך לשאילתא כמו שאני רוצה.

                  אין פה כללים, אם השאילתה מבטאת את מה שביקשת, אתה יכול לסמוך על EF בעיניים עצומות.
                  אתה רק צריך א. לא להשתמש בביטויים שלא נתמכים לתרגום לSQL, כמו פונקציות מקומיות וכדומה. זה מעיף שגיאה.
                  ב. לא לייצא את השאילתה לפני סוף התשאול, למשל בדוגמה הקודמת עם תעשה ToList לפני סיום ההתניה זה יהיה פלטור של Linq To Object ולא SQL בצד השרת.

                  פורסם במקור בפורום CODE613 ב01/06/2017 10:55 (+03:00)

                  מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                  בכל נושא אפשר ליצור קשר dovid@tchumim.com

                  תגובה 1 תגובה אחרונה
                  1
                  • רחמיםר מנותק
                    רחמיםר מנותק
                    רחמים מורחק
                    כתב ב נערך לאחרונה על ידי
                    #9

                    @דוד ל.ט.

                    var blogsWith = db.Blogs.Where(x => x.Tags.Any(y => y.id == 1) &&
                           x.Tags.Any(y => || y.id == 3));
                    

                    מצויין [רק צריך למחוק את ||]

                    כעת אני צריך להטמיע את זה בטופס הסינון שהמשתמשים יוכלו לחפש בלוגים על פי תגים שיש ו/או שאין
                    השאלה איך אני בונה ביטוי LINQ כזה בצורה דינמית שכמות התגים משתנה וגם כמובן מזהי התגים צריך להגדיר בזמן ריצה.

                    פורסם במקור בפורום CODE613 ב01/06/2017 11:00 (+03:00)

                    תגובה 1 תגובה אחרונה
                    1
                    • dovidD מנותק
                      dovidD מנותק
                      dovid ניהול
                      כתב ב נערך לאחרונה על ידי
                      #10

                      אם כוונתך איך לנסח את השאילתה מול ID של תגיות בצורה דינמית, אתה צריך לאחזר את רשימת התגיות הרלוונטיות ואח"כ לעבוד עם Contains בהתנייה. הנה למשל מתודה גמישה לזמן ריצה:

                      IQueryable<Blog> ByTags(IQueryable<Blog> blogs, IQueryable<Tag> have, IQueryable<Tag> prohibited)
                      {
                          var with = blogs.Where(x => have.All(y => x.Tags.Contains(y)));
                          return with.Where(x => !x.Tags.Any(y => prohibited.Contains(y)));
                      }
                      

                      קוד מריץ עם הקריטריונים לעיל:

                      var tagsTrue = db.Tags.Where(x => x.id == 1 || x.id == 3);
                      var tagsFalse = db.Tags.Where(x => x.id == 2 || x.id == 4);
                      
                      var blogs = ByTags(db.Blogs, tagsTrue, tagsFalse);
                      
                      Console.WriteLine(blogs);
                      

                      פורסם במקור בפורום CODE613 ב01/06/2017 13:05 (+03:00)

                      מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                      בכל נושא אפשר ליצור קשר dovid@tchumim.com

                      תגובה 1 תגובה אחרונה
                      1
                      • רחמיםר מנותק
                        רחמיםר מנותק
                        רחמים מורחק
                        כתב ב נערך לאחרונה על ידי
                        #11

                        תודה רבה,
                        החכמת אותי מאוד!

                        פורסם במקור בפורום CODE613 ב01/06/2017 13:08 (+03:00)

                        תגובה 1 תגובה אחרונה
                        1

                        בא תתחבר לדף היומי!
                        • התחברות

                        • אין לך חשבון עדיין? הרשמה

                        • התחברו או הירשמו כדי לחפש.
                        • פוסט ראשון
                          פוסט אחרון
                        0
                        • דף הבית
                        • קטגוריות
                        • פוסטים אחרונים
                        • משתמשים
                        • חיפוש
                        • חוקי הפורום