שאלה לגבי join ב-linq

saar85

New member
שאלה לגבי join ב-linq

היי לכולם. אני מנסה לעשות משהו ולא כל כך מצליח לי.
יש לי 2 טבלאות במסד נתונים.
אחת נקראת projects שיש בה כמה פרמטרים, ומפתח ראשי projectId.
וטבלה שניה שנקראת photos שגם בה יש כמה שדות. אבל השדות החשובים הם projectId שמקושר ל project.projectid ושדה שנקרא mainPhoto.
לכל פרויקט יש כמה תמונות. אבל כשאני מציג תקציר של הפרויקט אני רוצה שיראו רק את ה-mainPhoto. אני משתמש בlinq כדי למשוך נתונים. אבל פרויקטים שאין להם תמונות, או שאין להם תמונות שמוגדרות כmainPhoto לא מוצגים בכלל. אודה לעזרתכם בפתירה של הבעיה. אני מצטרף את השאילתא שכתבתי

קוד:
 var projects = from pro in db.Projects
                       join photo in db.Photos
                       on pro.projectId equals photo.projectId into photosGroup
                       from photo2 in photosGroup
                       where photo2.mainPhoto == true
                       orderby pro.projectId descending
                       select new
                       {
                           projectId = pro.projectId,
                           projectName = pro.projectName,
                           shortDescription = pro.shortDescription.Replace("\n", "<br/>"),
                           fileName = photo2.fileName,
                           description = photo2.description
                       };
וזו אפשרות שניה שניסיתי
קוד:
var projects = from pro in db.Projects
                       join photo in db.Photos
                       on pro.projectId equals photo.projectId
                       where photo.mainPhoto == true
                       orderby pro.projectId descending
                       select new
                       {
                           projectId = pro.projectId,
                           projectName = pro.projectName,
                           shortDescription = pro.shortDescription.Replace("\n", "<br/>"),
                           fileName = photo.fileName,
                           description = photo.description
                       };
בשני המקרים חוזר לי רק פרויקט שיש לו תמונות בטבלת תמונות שמקושרות אליו ופחות אחת מהן היא mainPhoto.

אודה לעזתרכם. תודה
 

nocgod

New member
ממה שהבנתי

זה אמור לתת לך את הפיתרון:
קוד:
var projects = 
	from pro in db.Projects
	join photo in (from p in db.Photos group p by p.projectId into photos select photos)
	on pro.projectId equals photo.Key into photosGroup
	from photo2 in photosGroup.DefaultIfEmpty()
	let mainPhoto = photo2?.SingleOrDefault(x => x.mainPhoto) ?? photo2?.FirstOrDefault()
	select new
	{
	   projectId = pro.projectId,
	   projectName = pro.projectName,
	   shortDescription = pro.shortDescription.Replace("\n", "<br/>"),
	   fileName = mainPhoto?.fileName,
	   description = mainPhoto?.description
	};

אם אין תמונות בכלל יהיה null
אם אין תמונה main תהיה הראשונה בgrouping (ללא מיון כלשהו)
אם יש תמונות שמוגדרות כ main תיבחר הראשונה מביניהן
קוד:
[{
	"projectId": "0c381e3259bb4b238e4257ab029e82cc",
	"projectName": "test",
	"shortDescription": "test description",
	"fileName": null,
	"description": null
},
{
	"projectId": "083087f4a4a14421a770bb3bb7c8eb2d",
	"projectName": "Project has photo",
	"shortDescription": "test description",
	"fileName": "photo_file.jpg",
	"description": "photo"
},
{
	"projectId": "0b3d48b361e44e5fbae0a51f96dd0492",
	"projectName": "Project has main photo",
	"shortDescription": "test main photo description",
	"fileName": "main_photo_file.jpg",
	"description": "main photo"
}]

(גילוי נאות: לא סובל את הsyntax הזה של linq)
 

saar85

New member
תודה

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

nocgod

New member
זה יותר אלגנטי לדעתי

קוד:
var projects = db.Projects
	.GroupJoin(db.Photos, x => x.projectId, x => x.projectId, (project, photos) =>
	{
		var mainPhoto = photos?.SingleOrDefault(x => x.mainPhoto) ?? photos?.FirstOrDefault();
		return new
		{
			projectId = project.projectId,
			projectName = project.projectName,
			shortDescription = project.shortDescription.Replace("\n", "<br/>"),
			fileName = mainPhoto?.fileName,
			description = mainPhoto?.description
		};
	});
 
למעלה