PDA

View Full Version : سوال: کوئری زدن بوسیله Task ها در EntityFramwork



barnamenevisjavan
یک شنبه 13 خرداد 1397, 12:13 عصر
سلام من توی برنامم کوئری هارو بصورت Task اجرا میکنم میخواستم ببینم نظر بقیه درموردش چیه؟ نرم افزار هم متوسط هستش و داده های زیادی نداره، ولی بصورت همزمان گاهی 3 یا 4 تا کوئری از جداول مختلف اجرا میشه. بیشتر برای پرفورمنس برنامه از task استفاده کردم
public async static Task<List<DataClass.Tables.User>> GetAllUserAsync()
{
using (var db = new DataClass.myDbContext())
{
var query = db.Users.Select(x => x);
return await query.ToListAsync();
}
}



var queryUser = GetAllUserAsync();
queryUser.Wait();


List<DataClass.Tables.User> dataUser = queryUser.Result;

ali_md110
دوشنبه 14 خرداد 1397, 00:38 صبح
کاربرد async بیشتر در web app کارایی دارد تا windows app
روش شما صحیح نیست دارید یک async رو به sync تبدیل میکند
نحوه صحیح بکارگیری async بدینظورت هست
اگر متدهاتون یک لیست بازگشتی هست و درون اون فقط یک دستور ToListAsync دارید و در جای دیگری صدا زده میشود از استفاده کردن async در تعریف تایع و await در بدنه خودداری کنید



public static Task<List<DataClass.Tables.User>> GetAllUserAsync()
{
using (var db = new DataClass.myDbContext())
{
var query = db.Users.Select(x => x);
return query.ToListAsync();
}
}

و و هنگام صدا زدن تابع بصورت زیر فراخوانی کنید


var queryUser =await GetAllUserAsync();

barnamenevisjavan
دوشنبه 14 خرداد 1397, 12:24 عصر
کاربرد async بیشتر در web app کارایی دارد تا windows app
روش شما صحیح نیست دارید یک async رو به sync تبدیل میکند
نحوه صحیح بکارگیری async بدینظورت هست
اگر متدهاتون یک لیست بازگشتی هست و درون اون فقط یک دستور ToListAsync دارید و در جای دیگری صدا زده میشود از استفاده کردن async در تعریف تایع و await در بدنه خودداری کنید



public static Task<List<DataClass.Tables.User>> GetAllUserAsync()
{
using (var db = new DataClass.myDbContext())
{
var query = db.Users.Select(x => x);
return query.ToListAsync();
}
}

و و هنگام صدا زدن تابع بصورت زیر فراخوانی کنید


var queryUser =await GetAllUserAsync();

حقیقتش این روش استفاده رو قبلا از تو یه وبلاگ خارجی یاد گرفته بودم، دیروز نشستم یه تایمر نوشتم که زمان بارگزاری کوئری رو برام برمیگردوند خیلی جالب بود وقتی از Task استفاده میکردم زمان اجرای برنامه 3 ثانیه و 600 هزارم ثانیه بود و مقدار 500 کیلوبایت از حافظه استفاده میکرد، وقتی بدون Task و بصورت معمولی کوئری نوشتم زمان اجرا به 3 ثانیه و 250 هزارم ثانیه و حافظه هم به 200 کیلوبایت کاهش پیدا کرد، حالا این روش شمارو هم تست میکنم ببینم بهینه هست یا ن

nunegandom
دوشنبه 14 خرداد 1397, 13:05 عصر
با سلام
async داستانش از این قراره که برنامه به صورت همزمانی کار کنه برای جلوگیری از هنگ کردن برنامه
حالا قضیه توی وب اینه که قراره با دیتابیس کار بشه و نمیخوایم برنامه وبمون هنگ کنه خوب از async استفاده میکنیم
یا میخوایم فایل دانلود یا آپلود کنیم یا هر کار سنگینی و جلوگیری از هنگ کردن برنامه و نه اینکه برنامه سرعتش بیاد بالا! در حقیقت پردازش برنامه همزمانی میشه ساده تر بگم:
میخوایم دوتا کامیون رو بار کنیم:
به صورت sync: کامیون اول رو بار میکنیم بعد کامیون دوم رو بار میکنیم
به صورت async: یه بهر میذاریم تو کامیون اول،‌یه بار میذاریم تو کامیون دوم و اینکارو ادامه میدیم تا کار جفتشون تموم شه!
همون قدر زمان میبره شاید async بیشتر! ولی هیچ کدوم صبر نمیکنن!:لبخند:

نکته دوم اینکه فکر میکنم آقای ali_md110 (http://barnamenevis.org/member.php?18325-ali_md110) اشتباه میکنند و شما کد رو صحیح نوشتید.
private async Task<IEnumerable<Pattern>> GetPatterns() {
return await _pattern.GetAll().Select(o => new Pattern { PatternName = o.PatternName, PatternId = o.PatternId }).ToListAsync();
}
model.Pattern = new SelectList(await GetPatterns());

barnamenevisjavan
دوشنبه 14 خرداد 1397, 14:39 عصر
با سلام
async داستانش از این قراره که برنامه به صورت همزمانی کار کنه برای جلوگیری از هنگ کردن برنامه
حالا قضیه توی وب اینه که قراره با دیتابیس کار بشه و نمیخوایم برنامه وبمون هنگ کنه خوب از async استفاده میکنیم
یا میخوایم فایل دانلود یا آپلود کنیم یا هر کار سنگینی و جلوگیری از هنگ کردن برنامه و نه اینکه برنامه سرعتش بیاد بالا! در حقیقت پردازش برنامه همزمانی میشه ساده تر بگم:
میخوایم دوتا کامیون رو بار کنیم:
به صورت sync: کامیون اول رو بار میکنیم بعد کامیون دوم رو بار میکنیم
به صورت async: یه بهر میذاریم تو کامیون اول،‌یه بار میذاریم تو کامیون دوم و اینکارو ادامه میدیم تا کار جفتشون تموم شه!
همون قدر زمان میبره شاید async بیشتر! ولی هیچ کدوم صبر نمیکنن!:لبخند:

نکته دوم اینکه فکر میکنم آقای ali_md110 (http://barnamenevis.org/member.php?18325-ali_md110) اشتباه میکنند و شما کد رو صحیح نوشتید.
private async Task<IEnumerable<Pattern>> GetPatterns() {
return await _pattern.GetAll().Select(o => new Pattern { PatternName = o.PatternName, PatternId = o.PatternId }).ToListAsync();
}
model.Pattern = new SelectList(await GetPatterns());


بله مفهوم async رو میدونم متاسفانه فکر میکردم یا حداقل راجبش فکر نکرده بودم که باعث کاهش سرعت و راندمان برنامه میشه، حالا این وسط یه چندتا چیز دیگه هستش برخی موقع ها میایم از Task استفاده میکنیم خشک و خالی، بعضی وقت ها داخل همین Task بصورت Async , Await استفاده میکنیم، اگر اطلاعی راجب این قضیه و نحوه کارکردش دارین ممنون میشم ازتون

ali_md110
دوشنبه 14 خرداد 1397, 15:42 عصر
با سلام

نکته دوم اینکه فکر میکنم آقای ali_md110 (http://barnamenevis.org/member.php?18325-ali_md110) اشتباه میکنند و شما کد رو صحیح نوشتید.
private async Task<IEnumerable<Pattern>> GetPatterns() {
return await _pattern.GetAll().Select(o => new Pattern { PatternName = o.PatternName, PatternId = o.PatternId }).ToListAsync();
}
model.Pattern = new SelectList(await GetPatterns());


من اشتباه نکردم دوست من
شما منظور من رو صحیح متوجه نشدید
کدی که دوستمون در سوالشون مطرج کردند غلط نیست جوابگو هست ولی سربار دارد


و در جواب سوال دوم شما BarnamenevisJavan


بله مفهوم async رو میدونم متاسفانه فکر میکردم یا حداقل راجبش فکر نکرده بودم که باعث کاهش سرعت و راندمان برنامه میشه، حالا این وسط یه چندتا چیز دیگه هستش برخی موقع ها میایم از Task استفاده میکنیم خشک و خالی، بعضی وقت ها داخل همین Task بصورت Async , Await استفاده میکنیم، اگر اطلاعی راجب این قضیه و نحوه کارکردش دارین ممنون میشم ازتون


دقیقا من جواب شما رو در پست قبلی دادم

هر زمان یک متدی دارید که درون اون فقط یک لیست و یا بهتر بگم یک کوئری tolistAsync دارید نیاز به تعریف async در تعریف امضای متد و await در بدنه کد نیست
مثل تابع اولی خودتون
مثلا اگر تابعی دارید بدینصورت



public async Task GetAllUserAsync()
{
var list=await dbcontext.person.ToListAsync();
var list2=await dbcontext.persondetails.ToListAsync();
foreach(var p in list)
var li=list2.first(x=> x.id=p.id);
}


چون در این تابع از جدول person واکشی کردیم وبلافاصله به نتیجه اون در همین متد نیاز داریم مجبوریم از async و await در این متد استفاده کنیم کامپایلر هم به ما هشدار میدهد

برای صدا زدن بدینصورت عمل نکنید


GetAllUserAsync.waite()

صحیحش بدینصورت هست


await GetAllUserAsync();

ولی اگر یک متد داریم که فقط یک tolist دارد و در سایر متدها ی دیگر قابل استفاده میکنیم جهت سربار کمتر امضای متد را بدون async و await را هم از بدنه کد حذف کنید
و هنگام صدا زدن کافیه قبل از متد await را بکار ببریم


Task List<Person>Get()
{
return dbcontext.persons.ToListAsync();
}



async Task CallMetod()
{
var i=await Get()
}

barnamenevisjavan
دوشنبه 14 خرداد 1397, 17:04 عصر
من اشتباه نکردم دوست من
شما منظور من رو صحیح متوجه نشدید
کدی که دوستمون در سوالشون مطرج کردند غلط نیست جوابگو هست ولی سربار دارد


و در جواب سوال دوم شما BarnamenevisJavan


دقیقا من جواب شما رو در پست قبلی دادم

هر زمان یک متدی دارید که درون اون فقط یک لیست و یا بهتر بگم یک کوئری tolistAsync دارید نیاز به تعریف async در تعریف امضای متد و await در بدنه کد نیست
مثل تابع اولی خودتون
مثلا اگر تابعی دارید بدینصورت



public async Task GetAllUserAsync()
{
var list=await dbcontext.person.ToListAsync();
var list2=await dbcontext.persondetails.ToListAsync();
foreach(var p in list)
var li=list2.first(x=> x.id=p.id);
}


چون در این تابع از جدول person واکشی کردیم وبلافاصله به نتیجه اون در همین متد نیاز داریم مجبوریم از async و await در این متد استفاده کنیم کامپایلر هم به ما هشدار میدهد

برای صدا زدن بدینصورت عمل نکنید


GetAllUserAsync.waite()

صحیحش بدینصورت هست


await GetAllUserAsync();

ولی اگر یک متد داریم که فقط یک tolist دارد و در سایر متدها ی دیگر قابل استفاده میکنیم جهت سربار کمتر امضای متد را بدون async و await را هم از بدنه کد حذف کنید
و هنگام صدا زدن کافیه قبل از متد await را بکار ببریم


Task List<Person>Get()
{
return dbcontext.persons.ToListAsync();
}



async Task CallMetod()
{
var i=await Get()
}

بسیار ممنون من هر 3 مورد رو تست کردم یعنی مورد اول که خودم بصورت Task و wait نوشته بودم، موردی که شما عنوان کردین بصورت await و مورد اخر روش کاملا ساده و نرمال و بدون Taskها نتیجه زیر بدست اومد

Task=> Elapsed time: 00:00:03.5856344, Memory Usage: 30,540/00 KB
Await=> Elapsed time: 00:00:03.0463108, Memory Usage: 30,452/00 KB
Normal=> Elapsed time: 00:00:02.9569964, Memory Usage: 30,240/00 KB

موردی که شما گفتین در مقایسه با روش Task من زمان کمتر و حافظه کمتری برای اجرا میبره و همینطور روش نرمال هم زمان کمتری میبره هم حافظه کمتری،البته روی یه جدول با داده کم تست کردم احتمالا روی داده های زیاد نتایج فرق بکنه
راستی پیشنهادی ، نکته ای چیزی برای پرفورمنس بهتر دارین؟ هم زمان اجرا کم کنیم هم حافظه رو

nunegandom
دوشنبه 14 خرداد 1397, 18:12 عصر
درست میفرمایید بنده اشتباه متوجه شدم:خجالت:
حرکت جالی بود
دیدم شما هم توی قسمت وب فعالیت میکنید.
توی وب مشکلی از لحاظ تعداد Thread ها از سمت هاستینگ پیش نمیاد اگر یک همچین کاری کنیم؟ قاطی نمیکنه ؟
اگر دیتا رو بخوایم بگیریم به صورت Task و خط بعد روی اون کاری انجام بدیم بدوم await به خطا میخوریم درسته؟

ali_md110
دوشنبه 14 خرداد 1397, 18:13 عصر
روش normal منظورتون چیه ؟منوجه نشدم
دستور جدید سی شارپ هست؟
پرفرومنس خاصی نیست
همین موردی که من گفتم رعایت کنید
مزیت مهم Async اینه که اگر یک عملیات مثلا 5 دقیقه طول بکشه تا لیست به کاربر نشون داده بشه چنانچه همزمان 5 کاربر دیگر همین درخواست را بدهند نیاز نیست صبر کنند 5 دقیقه شخص اول تمام شود و موازی با هم تمام میشوند
در ضمن حافظه ها امروزه خیلی بزرگ شدند نگران حافظه نباشید
در کونری هاتون اگر لیست واکشی شده فقط خواندنی هست AsNoTracking بکار ببرید
بکارگیری یک IOC کانتینر خیلی میتونه کمک کنه
از ترزیق وابستکی ها استفاده کنید
تا جاییکه امکان دارید متد یا متغیر استاتیک نسازید
اگر متدهاتون یک لیست بر میگرداند آخر متد را با ToList ببندید
حتمن از Automapper استفاده کنید سرعت واکشی بالاتری دارد
جهت لودینگ اطلاعات زیاد نمایشی از paging استفاده کنید
لینک زیر هم مطالعه کنید خیلی مفید ست
https://www.thereformedprogrammer.net/six-ways-to-build-better-entity-framework-core-and-ef6-applications/

ali_md110
دوشنبه 14 خرداد 1397, 18:36 عصر
خب تا await بکار نبرید نتیحه ای هم ندارید پس الزام هستید و در ضمن خطای کامپایلری هم دارید

barnamenevisjavan
دوشنبه 14 خرداد 1397, 19:03 عصر
روش normal منظورتون چیه ؟منوجه نشدم
دستور جدید سی شارپ هست؟
پرفرومنس خاصی نیست
همین موردی که من گفتم رعایت کنید
مزیت مهم Async اینه که اگر یک عملیات مثلا 5 دقیقه طول بکشه تا لیست به کاربر نشون داده بشه چنانچه همزمان 5 کاربر دیگر همین درخواست را بدهند نیاز نیست صبر کنند 5 دقیقه شخص اول تمام شود و موازی با هم تمام میشوند
در ضمن حافظه ها امروزه خیلی بزرگ شدند نگران حافظه نباشید
در کونری هاتون اگر لیست واکشی شده فقط خواندنی هست AsNoTracking بکار ببرید
بکارگیری یک IOC کانتینر خیلی میتونه کمک کنه
از ترزیق وابستکی ها استفاده کنید
تا جاییکه امکان دارید متد یا متغیر استاتیک نسازید
اگر متدهاتون یک لیست بر میگرداند آخر متد را با ToList ببندید
حتمن از Automapper استفاده کنید سرعت واکشی بالاتری دارد
جهت لودینگ اطلاعات زیاد نمایشی از paging استفاده کنید
لینک زیر هم مطالعه کنید خیلی مفید ست
https://www.thereformedprogrammer.net/six-ways-to-build-better-entity-framework-core-and-ef6-applications/
نرمال منظورم به این صورت بود
using (var db = new DataClass.myDbContext())
{
var query = db.Schools.ToList();
}