خوب اول برای این که بفهمیم سمت کلاینت و سرور اینجا معنیش چیه سرور یعنی همون دیتابیس سمت کلاینت هم یعنی سمت یوزر حالا اگر ما کد نویسیم که اون کد نتونه تبدیل به TSQL بشه ef میاد کل دیتا رو از دیتا بیس میخونه و بعد میاره توی برنامه و بعد اون دیتایی که میخوایم رو از توش درمیاره ، این یعنی چی ؟ یعنی این که که مثلا ما 5 تا مورد رو میخوایم نمایش بدیم توی سایت ولی چون دستورش به TSQL تبدیل نشده میاد کل دیتای دیتا بیس که ممکنه 1000 تا باشه رو از دیتا بیس میخونه و بعد میاد اون 5 تا رو ازش جدا میکنه و نمایش میده از ورژن های بعد 3 نسخه ef اینطوری شده که اگر ef نتونه تبدیل به TSQL رو انجام بده ارور میده مثال: فرض کنید که میخوایم مالیات محصولاتمون رو محاسبه کنیم :
حالا میایم یه شرط میزاریم و میگیم که اون هایی که مالیاتشون بیشتر از 1000 هستش رو بهمون بده
خوب نکته ای که وجود داره اینه که چون یه کد سی شارپ نوشتیم برای محاسبه مالیات باید اول تمامی دیتا ها از سرور بیاد توی برنامه و بعد این متد روش اعمال بشه و بعد نتیجه بدست بیاد
و با این ارور مواجه میشیم
برای این که بخوایم این کار رو بکنیم باید از enumarable استفاده کنیم
این query میره و تمام دیتا ها رو لود میکنه توی برنامه و اگر تعداد رکورد ها زیاد باشه برنامه مون میپوکه
حالا تفاوت بالایی با پایینی در اینه که پایینی در دیتابیس اجرا میشه
توی این تصویر بالا میبینید که با استفاده از where اون هایی که بیشتر از 9000 تومن بودن رو داره لود میکنه توی ورژن های قبل از 3 هم اگر خواستیم سیستم هشدار رو برای این قضیه فعال کنیم از این دستور استفاده میکنیم
موضوع TRACKING در ef اینطوریه که وقتی که دیتایی رو از دیتابیس میاریم توی برنامه دیگه اونجا هست و جاهای دیگه میتونیم ازش استفاده کنیم
اینجا به طور مثال در حالتی که tag ها رو ما قبل از post ها لود نکنیم ، وقتی که پست ها لود میشن هیچکدوم از realtion هاشون لود نمیشه ولی وقتی که tag رو قبلش لود کردیم ، توی پست relation که به tag داشته رو نشون میده ، چون از قبل لود شده و توی برنامه هست
نکته ی بعدی
اینجا وقتی که از where استفاده میکنیم میره و از دیتابیس دیتا ها رو میگیره و میاره ولی توی find چون ما از قبل اومدیم دیتا رو گرفته بودیم از دیتا بیس و وارد برنامه کردیم دیگه به دیتابیس برای گرفتن دیتای tag دومی query نمیزنه
اینطوری ef کار میکنه که اول میره از snap shot خودش استفاده میکنه اگر اونجا پیداش نکنه میره به دیتابیس query میزنه
کجا باید از tracking استفاده کنیم کجا از no tracking
اگر entity داشته باشیم که کلید اصلی نداشته باشه یا keyless باشه به صورت پیش فرض no track هستش اگر دیتایی که داریم از دیتابیس میاریم نیازی نداره جای دیگه برنامه استفاده بشه پس نیازی نداره track بشه و خوده track کردن سر بار برنامه ایجاد میکنه پس دیتایی که نیاز نداریم جای دیگه برنامه استفاده بشه track نکنیم
برای این کار میتونیم دیتابیس رو بر روی no tracking تنظیم کنیم
خوب دیگه اینجا وقتی که دیتای توی post رو نگاه میکنیم tag ها داخلش نیستن
و نکته ای که وجود داره اینه که find هم میره مستقیم از دیتابیس میخونه
نکته ی بعدی اینه که حتی وقتی که میخوایم چیزی رو در دیتا بیس تغییر بدیم هم باید از tracking استفاده کنیم و بدون tracking تغییرات انجام نمیشه
در عکس بالا تغییرات انجام نمیشه
دیتا هایی که فقط میخوایم بخونمیشون read only هستن رو دیگه لزومان واجب نیست که tracking کنیم
راه بعدی استفاده از متد as no tracking هستش
حالا یه موقع هست که میخوایم خودمون به صورت مستقیم با استفاده از TSQL بیایم یه سری دیتا ها رو بخونیم
خوب اول از context که دیتا بیس هستش استفاده میکنیم و بعد میگیم entity که انتخاب کردیم post هستش و بعد دستور fromSqlRaw برای نوشتن tsql استفاده میکنیم
خوب select که میشه انتخاب کردن ، * یعنی تمامی فیلد ها ، بعدش from و اسم اسکیما مون رو مینویسیم که اینجا dbo هستش و بعدش هم نام جدول که posts هستش
توی ef یه سری فیلتر هستش که ما میتونیم روی تمام query هایی که در برنامه انجام میشه به صورت global اعمال کنیم خوب این به چه کاری میاد ؟ برای این که مثلا فرض کنید که ما یه پراپرتی isRemoved داریم که این وقتی که فعال باشه یعنی دیتا از روی دیتابیس پاک شده و دیگه نیازی نیست که اون رو لود کنیم برای همین میایم یه فیلتر سراسری برای این قضیه مینونیسیم
برای این کار میایم این کار و میکنیم
اینطوری تمام query هایی که روی user زده میشه اون هایی که isRemoved براشون غیر فعال باشه دیتاشون رو میاره
خوب حالا برای این که بخوایم این فیلتر رو غیر فعال کنیم این کار رو باید انجام بدیم
تفاوت IEnumarable و IQeryable
این خیلی جالبه
این دستور اجرا میشه ولی دیتایی از دیتابیس خونده نمیشه بیاد توی برنامه و فقط زمانی دیتا لود میشه که بهش نیاز داشته باشیم ، مثلا زمانی که میزنیم روش میخوایم داخلش رو ببینیم میره و دیتا رو میاره
هر بار هم بزنیم روش بازم میره میاره و این رو توی profiler نشون میده
خوب حالا توی این حالت مجبوره که بره و دیتا رو بیاره چون از to list استفاده کردیم و دیتا رو باید بگیره و بریزه توی لیست و حتما اجرا میشه
نکته ی خیلی مهمی که وجود داره اینه که این دستور تمام دیتاهای دیتا بیس رو اورده توی برنامه و بعد اون شرط contains M رو روش پیاده کرده
ولی Iqueryable اینطوری نیست
توی Iqueryable میره اون دستور توی دیتابیس اجرا میشه و نتیجه اش رو میاره توی برنامه حالا نکته ای که وجود داره اینه که این دو تا دستور یکی هستن ولی هر کدوم متفاوت اجرا میشن توی IEnamerable چون data ها میاد توی برنامه و بعد ما روشون دستور رو اجرا میکنیم چون توی C# حروف بزرگ و کوچک مهم هستش میاد فقط اون هایی که M بزرگ دارند رو میاره ولی همین دستور وقتی که توی SQL اجرا میشه چون اونجا براش بزرگ و کوچیک مهم نیست همه ی اون های که m دارند چه بزرگ و چه کوچیک رو میاره
وقتایی که داریم repositry کار میکنیم میایم از IEnamarable استفاده میکنیم که کسی در لایه های بالاتر نتونه query دیگه بزنه به دیتا بیس
وقتایی هم که میخوایم یه شرطی رو روی دیتا ها چک کنیم میایم از IQueryable استفاده میکنیم دستور هایی که توی linq داشتیم همه تبدیل به کد های TSQL میشه و سمت دیتابیس استفاده میشه