جدول Post با جدول GroupsDetail ارتباط یک به چند و در مقابل ان جدول GroupsDetail با جدول PostGroup ارتباط چند به یک دارد . به زبان ساده ما تعدادی گروه بندی برای مطالب داریم (در جدول PostGroup) و میتوانیم برای هر مطلب تعدادی از گروهها را در جدول GroupsDetail مشخص کنیم ...
فکر میکنم همین مقدار توضیح به اندازهی کافی برای درک روابط مشخص شده در مدل رابطه ای مفروض کفایت کند.
حالا فرض کنید ما میخواهیم لیستی از عنوان مطالب موجود به همراه [نام] گروههای هر مطلب را داشته باشیم .
توجه شما رو به قطعه کد سادهی زیر جلب میکنم:
var context = new Models.EntitiesConnection(); var query = context.Posts.Select(pst => new { id = pst.id, Title = pst.Title, GNames = pst.GroupsDetails.Select(grd => new { Name = grd.PostGroup.name }) }) .OrderByDescending(c => c.id) .ToList();
خب میرسیم به ادامهی مطلبمون . نتیجهی این query چه خواهد بود ؟ کاملا واضح است که ما تعداد دلخواهی از فیلدها رو برای واکشی مشخص کردیم پس در نتیجه نوع داده ای که توسط این query بازگشت داده خواهد شد یک لیست از یک نوع بی نام میباشد ... چگونه از نتیجهی بازگشتی این query در صورت ارسال اون به عنوان یک پارامتر به یک تابع استفاده کنیم ؟ اگر ما تمامی فیلدهای جدول Post را واکشی میکریم مقدار بازگشتی یک لیست از نوع Post بود که به راحتی قابل استفاده بود مثل مثال زیر
public bool myfunc(List<Post> query) { foreach (var item in query) { ..... string title = item.Title; } ...return true; } . . . var context = new Models.EntitiesConnection(); var queryx = context.Posts.ToList(); .... myfunc(queryx );
1 : استفاده از Reflection برای دسترسی به فیلدهای مشخص شده .
2 : تعریف یک مدل کامل بر اساس فیلدهای مشخص شدهی بازگشتی و ارسال یک لیست از نوع تعریف شده به تابع . ( به نظرم این روش خسته کنندست و زیاد شکیل نیست چون برای هر query خاص مجبوریم یک مدل کلی تعریف کنیم و این باعث میشه تعداد زیادی مدل در نهایت داشته باشیم که استفادهی زیادی از اونها نمیشه عملا )
3 : استفاده از یکی از روشهای خلاقانهی تبدیل نوع Anonymousها .
روش سوم روش مورد علاقهی من هست و انعطاف بالایی داره و خیلی هم شیکو مجلسیه ! در ضمن این روش که قراره ذکر بشه کاربردهای فراوانی داره که این مورد فقط یکی از اونهاست
خب بریم سر اصل مطلب . به کد زیر توجه کنید :
public static List<T> CreateGenericListFromAnonymous<T>(object obj, T example) { return (List<T>)obj; } public static IEnumerable<T> CreateEmptyAnonymousIEnumerable<T>(T example) { return new List<T>(); ; } //// public bool myfunc(object query) { var cquery = CreateGenericListFromAnonymous(query, new { id = 0, Title = string.Empty, GNames = CreateEmptyAnonymousIEnumerable(new { Name = string.Empty }) }); foreach (var item in cquery) { string title = item.Title; foreach (var gname in item.GNames) { string gn = gname.Name; } . . . } return false; } . . . var context = new Models.EntitiesConnection(); var query = context.Posts.Select(pst => new { id = pst.id, Title = pst.Title, GNames = pst.GroupsDetails.Select(grd => new { Name = grd.PostGroup.name }) }).OrderByDescending(c => c.id); myfunc(query.ToList());
تابع CreateGenericListFromAnonymous : یک object رو میگیره و اون رو به یک لیست تبدیل میکنه بر اساس نوعی که به صورت inline براش مشخص میکنیم .
تابع CreateEmptyAnonymousIEnumerable یک لیست از نوع IEnumerable رو بر اساس نوعی که به صورت inline براش مشخص کردیم بر میگردونه . دلیل اینکه من در اینجا این تابع رو نوشتم این بود که ما در query یک فیلد با نام GNames داشتیم که مجموعه ای از نام گروههای هر مطلب بود که از نوع IEnumerable هستش . در واقع ما در اینجا نوع بی نامی داریم که یکی از فیلدهای اون یک لیست از یک نوع بی نام دیگست . امیدوارم مطلب براتون جا افتاده باشه.
دوستان عزیز سوالی بود در قسمت نظرات مطرح کنید.