PDA

View Full Version : سوال: خطا در اجرای کوئری لینک در تابع Async Task



barnamenevisjavan
پنج شنبه 16 فروردین 1397, 15:25 عصر
سلام من قبلا از طریق کد زیر کوئری مورد نظرم رو داخل تابع async Task اجرا میکردم و بدون مشکل هستش:
public async static Task<List<DataClass.Tables.Student>> GetAllStudentsAsync()
{
using (var db = new DataClass.myDbContext())
{
var query = from item in db.Students
select item;
return await query.ToListAsync();
}
}

الان نیاز دارم تا اطلاعات رو با جدول دیگه ای ترکیب کنم و بعدش سلکت کنم کدهام رو به این صورت نوشتم:
public async static Task<List<DataClass.Tables.Student>> GetAllStudentsAsync()
{
using (var db = new DataClass.myDbContext())
{
var query = from c in db.Schools
join v in db.Students on c.Id equals v.BaseId
select new { v.Name, v.LName, v.FName, v.Gender, v.BaseId, v.Image, c.Base };


return await query.ToListAsync();
}
}


اما در خط return await query.ToListAsync(); برنامه دچار خطا میشه و اجازه کامپایل نمیده چطور این مشکل رو باید حل کنم؟

mr.sirwan
پنج شنبه 16 فروردین 1397, 15:37 عصر
خب کوئری شما یه لیست ترکیبی رو برمیگردونه اما نوع بازگشتی تابع از نوع لیست student هست، شما میتونین یه کلاس بسازین با فیلدهایی که میخواین برگشت داده بشن، نوع برگشتی تابع رو به اون کلاس تغییر بدین و توی Select نام اون کلاس رو ذکر کنین

barnamenevisjavan
پنج شنبه 16 فروردین 1397, 15:46 عصر
خب کوئری شما یه لیست ترکیبی رو برمیگردونه اما نوع بازگشتی تابع از نوع لیست student هست، شما میتونین یه کلاس بسازین با فیلدهایی که میخواین برگشت داده بشن، نوع برگشتی تابع رو به اون کلاس تغییر بدین و توی Select نام اون کلاس رو ذکر کنین
میشه یه مثال بزنید؟ کلاس رو به چه صورت ایجاد کنم؟ چون مثل کلاس های جدول ساختم باز هم همون خطا رو میده

mr.sirwan
پنج شنبه 16 فروردین 1397, 15:54 عصر
public class SchoolsStudentsJointDto
{
public string Name { get; set; }
public string LName { get; set; }
public string FName { get; set; }
public string Gender { get; set; }
public int BaseId { get; set; }
public byte[] Image { get; set; }
public virtual Base Base { get; set; }
}

لازم نیست این کلاس رو توی مدلتون پیاده کنین، تو هر جایی از پروژه باشه اشکالی نداره، اما بهتره یه پروژه ایجاد کنین و اینجور کلاسارو داخل اونا تعریف کنین
به این روش الگوی طراحی شی انتقال داده یا Data Transfer Object یا به اختصار Dto گفته میشه، درموردش جستجو کنین، الگوی کارامدی هستش

barnamenevisjavan
پنج شنبه 16 فروردین 1397, 16:05 عصر
public class SchoolsStudentsJointDto
{
public string Name { get; set; }
public string LName { get; set; }
public string FName { get; set; }
public string Gender { get; set; }
public int BaseId { get; set; }
public byte[] Image { get; set; }
public virtual Base Base { get; set; }
}

لازم نیست این کلاس رو توی مدلتون پیاده کنین، تو هر جایی از پروژه باشه اشکالی نداره، اما بهتره یه پروژه ایجاد کنین و اینجور کلاسارو داخل اونا تعریف کنین
به این روش الگوی طراحی شی انتقال داده یا Data Transfer Object یا به اختصار Dto گفته میشه، درموردش جستجو کنین، الگوی کارامدی هستش
بسیار ممنون فقط این که کلاسی که نوشتین به مورد اخر گیر میده
public virtual Base Base { get; set; }



کلاس Base من ندارم

mr.sirwan
پنج شنبه 16 فروردین 1397, 16:15 عصر
بنده با توجه به فیلد BaseId فک کردم این فیلد Base یک کلاسه، شما اون رو به نوعی که هست تغییر بدین، و کلمه کلیدی virtual رو حذف کنین

barnamenevisjavan
پنج شنبه 16 فروردین 1397, 16:19 عصر
بنده با توجه به فیلد BaseId فک کردم این فیلد Base یک کلاسه، شما اون رو به نوعی که هست تغییر بدین، و کلمه کلیدی virtual رو حذف کنین
من الان طبق فرمایش شما به این صورت تغییر دادم ولی همچنان مشکل پابرجاست:
public async static Task<List<SchoolsStudentsJointDto>> GetAllStudentsAsync() {
using (var db = new DataClass.myDbContext())
{
var query = from c in db.Schools
join v in db.Students on c.Id equals v.BaseId
select new { v.Name, v.LName, v.FName, v.Gender, v.BaseId, v.Image, v.Id, c.Base };




return await query.ToListAsync();
}
}
public class SchoolsStudentsJointDto
{
public string Name { get; set; }
public string LName { get; set; }
public string FName { get; set; }
public string Gender { get; set; }
public int BaseId { get; set; }
public byte[] Image { get; set; }
public string Base { get; set; }
}

mr.sirwan
پنج شنبه 16 فروردین 1397, 16:29 عصر
گفتم که نام کلاس رو در کوئری select ذکر کنین:
select new SchoolsStudentsJointDto { Name = v.Name, LName= v.LName, =FName v.FName, Gender= v.Gender, BaseId= v.BaseId, Image = v.Image, Id = v.Id, Base = c.Base };

barnamenevisjavan
پنج شنبه 16 فروردین 1397, 16:34 عصر
گفتم که نام کلاس رو در کوئری select ذکر کنین:
select new SchoolsStudentsJointDto { Name = v.Name, LName= v.LName, =FName v.FName, Gender= v.Gender, BaseId= v.BaseId, Image = v.Image, Id = v.Id, Base = c.Base };


:لبخند: دوست عزیز بسیار ممنون مشکلم حل شد حواسم به سلکت نبود تشکر از وقتی که گذاشتین:تشویق:

mr.sirwan
پنج شنبه 16 فروردین 1397, 16:37 عصر
خواهش میکنم، لطفا از دکمه تشکر استفاده کنین

مهرداد صفا
جمعه 17 فروردین 1397, 17:37 عصر
سلام من قبلا از طریق کد زیر کوئری مورد نظرم رو داخل تابع async Task اجرا میکردم و بدون مشکل هستش:
public async static Task<List<DataClass.Tables.Student>> GetAllStudentsAsync()
{
using (var db = new DataClass.myDbContext())
{
var query = from item in db.Students
select item;
return await query.ToListAsync();
}
}

الان نیاز دارم تا اطلاعات رو با جدول دیگه ای ترکیب کنم و بعدش سلکت کنم کدهام رو به این صورت نوشتم:
public async static Task<List<DataClass.Tables.Student>> GetAllStudentsAsync()
{
using (var db = new DataClass.myDbContext())
{
var query = from c in db.Schools
join v in db.Students on c.Id equals v.BaseId
select new { v.Name, v.LName, v.FName, v.Gender, v.BaseId, v.Image, c.Base };


return await query.ToListAsync();
}
}


اما در خط return await query.ToListAsync(); برنامه دچار خطا میشه و اجازه کامپایل نمیده چطور این مشکل رو باید حل کنم؟

سلام.
اگر از C#‎ 7 استفاده می کنید نیاز به ساخت کلاس جدید ندارید و میتونید از Tuple (https://msdn.microsoft.com/en-us/library/system.tuple(v=vs.110).aspx) استفاده کنید.
نوع و نام فیلد ها رو داخل پرانتز تعریف کنید.



public async static Task<List<(string Name , string LName,string FName, string Gender,string BaseId,object Image, object Base)>> GetAllStudentsAsync()
{
using (var db = new DataClass.myDbContext())
{
var query = from c in db.Schools
join v in db.Students on c.Id equals v.BaseId
select (v.Name, v.LName, v.FName, v.Gender, v.BaseId, v.Image, c.Base );


return await query.ToListAsync();
}


البته ناگفته نمونه که این روش برای متودهای public الگوی جالبی نیست و بیشتر برای متودهای private و internal مناسبه

barnamenevisjavan
جمعه 17 فروردین 1397, 20:49 عصر
سلام.
اگر از C#‎‎ 7 استفاده می کنید نیاز به ساخت کلاس جدید ندارید و میتونید از Tuple (https://msdn.microsoft.com/en-us/library/system.tuple(v=vs.110).aspx) استفاده کنید.
نوع و نام فیلد ها رو داخل پرانتز تعریف کنید.



public async static Task<List<(string Name , string LName,string FName, string Gender,string BaseId,object Image, object Base)>> GetAllStudentsAsync()
{
using (var db = new DataClass.myDbContext())
{
var query = from c in db.Schools
join v in db.Students on c.Id equals v.BaseId
select (v.Name, v.LName, v.FName, v.Gender, v.BaseId, v.Image, c.Base );


return await query.ToListAsync();
}


البته ناگفته نمونه که این روش برای متودهای public الگوی جالبی نیست و بیشتر برای متودهای private و internal مناسبه
ممنون میشه بگید تفاوت استفاده در متد public و private چیه؟

مهرداد صفا
جمعه 17 فروردین 1397, 22:12 عصر
ممنون میشه بگید تفاوت استفاده در متد public و private چیه؟

خواهش می کنم.
اگر قرار باشه که یک کتابخانه عمومی بنویسید که احتمالا برنامه نویسان دیگه ای از اون استفاده کنند بهتره که مقادیر برگشتی رو درون یک کلاس تعریف کنید و یک کلاس رو برگردونید. اینطوری کد خواناتری خواهید داشت و استفاده از متود ساده تر خواهد بود.
ولی با توجه به امکان جدیدی که برای نامگذاری آیتمهای Tuple به C# اضافه شده، استفاده از Tuple برای مصرف خودتون و داخل متودهای داخلی کار رو خیلی ساده تر میکنه و خیلی مواقع شما رو از تعریف کلاس جدید برای انتقال داده بی نیاز میکنه.
یعنی در موارد مشابه به مشکل شما، برای برگردوندن چند مقدار نیاز نیست که یک کلاس جدید تعریف بشه بلکه Tuple اینجا میتونه مفید باشه.