#EfCore_Best_Practice
Solve the problem 1+N in Ef Core
حل مشکل 1+N در Ef Core
این مشکل در correlated subqueries رخ میدهد.
به عنوان مثال در کوئری زیر
و به ازای هر
این مشکل با نام مشکل 1+N شناحته میشود.
از Ef Core 2.1 به بعد
کوئری اول سلکتی برای
برای انجام اینکار هم نیاز به انجام یک تغییر کوچک در کوئری خود دارید.
اطلاعات بیشتر در مورد این مسئله را می توانید در Issue 4007 مربوط به ریپازیتوری Ef Core مشاهده و دنبال کنید.
@fullStackDevs
Solve the problem 1+N in Ef Core
حل مشکل 1+N در Ef Core
این مشکل در correlated subqueries رخ میدهد.
به عنوان مثال در کوئری زیر
var query = context.Customers.Select(
c =>
c.Orders.Where(o => o.Amount > 100).Select(o => o.Amount)
);
ابتدا کوئری برای دریافت لیستی از Customers
به دیتابیس ارسال میشود .و به ازای هر
Customer
کوئری زیر c.Orders.Where(o => o.Amount > 100).Select(o => o.Amount)
ترجمه و به سمت دیتابیس ارسال میشود.این مشکل با نام مشکل 1+N شناحته میشود.
از Ef Core 2.1 به بعد
Optimization
ای برای این قبیل کوئری ها انجام شده است که از وقوع این مشکل جلوگیری میکند و سبب میشود که کوئری بالا حداکثر به دو اس کیو ال کوئری ترجمه شود.کوئری اول سلکتی برای
Customer
ها و کوئری دوم اعمال فیلتری بر روی Order
هابرای انجام اینکار هم نیاز به انجام یک تغییر کوچک در کوئری خود دارید.
var query = context.Customers.Select(
c => c.Orders.Where(o => o.Amount > 100).Select(o => o.Amount).ToList());
کافیست به SubQuery
خود متد ToList()
را اضافه کنید .اطلاعات بیشتر در مورد این مسئله را می توانید در Issue 4007 مربوط به ریپازیتوری Ef Core مشاهده و دنبال کنید.
@fullStackDevs
GitHub
Query: Optimize navigation property translation in projections · Issue #4007 · aspnet/EntityFrameworkCore
For example, customers.Select(c => new { c.Id, Orders = c.Orders }) results in n+1 at the moment. Make sure to consider the following scenarios when looking at this: #5754 #5738 #5791
#EfCore_Best_Practice
#Explicit_compiled_queries
در این پست به معرفی یک ویژگی باحال که از EF 5 به بعد و در LINQ to SQL نیز وجود داشت و در EF Core از نسخه 2.0 به آن افزوده شد می پردازیم.
در ابتدا Ef Core در ورژن 1.0 ویژگی query caching را معرفی کرد . این ویژگی علاوه بر پرفورمنسی که دارد اما دارای سربارهایی نیز است.
هر کوئری برای کش شدن و نگه داری آن در حافظه و سپس استفاده مجدد از آن به یک کلید هش شده نیاز دارد که تولید این کلید هش شده از روی Query Expression سرباری دارد.
اما از نسخه Ef Core2.0 ویژه گی query compilation به آن اضافه شده.
در این حالت کوئری یک بار کامپایل شده و در حافظه نگه داری میشود و می توانید به هر دفعات که خواستید از ان استفاده کنید.
Example:
usage :
1-کوئری تان قرار است خیلی بیشتر از یک بار متوالی اجرا شود.
2-کوئری شما به قدر کافی پیچیده است و هزینه هربار کامپایل ان زیاد است.
* نکته اول اگر دلیگیت کامپایل کوئری مورد نظر خود را به صورت استاتیک تعریف کنید می توانید در تمام نمونه های ApplicationDbContext خود از آن استفاده کنید.
*نکته دوم نسخه جاری Ef Core هنوز نوع خروجی
@fullStackDevs
#Explicit_compiled_queries
در این پست به معرفی یک ویژگی باحال که از EF 5 به بعد و در LINQ to SQL نیز وجود داشت و در EF Core از نسخه 2.0 به آن افزوده شد می پردازیم.
در ابتدا Ef Core در ورژن 1.0 ویژگی query caching را معرفی کرد . این ویژگی علاوه بر پرفورمنسی که دارد اما دارای سربارهایی نیز است.
هر کوئری برای کش شدن و نگه داری آن در حافظه و سپس استفاده مجدد از آن به یک کلید هش شده نیاز دارد که تولید این کلید هش شده از روی Query Expression سرباری دارد.
اما از نسخه Ef Core2.0 ویژه گی query compilation به آن اضافه شده.
در این حالت کوئری یک بار کامپایل شده و در حافظه نگه داری میشود و می توانید به هر دفعات که خواستید از ان استفاده کنید.
Example:
private static Func<AdventureWorksContextDI, int, Orders> _getOrderById =
EF.CompileQuery((AdventureWorksContextDI context, int id) =>
context.WorkOrders.Select(
x => new Orders
{
Id = x.WorkOrderId,
ProductName = x.Product.Name,
Quantity = x.OrderQty,
Date = x.DueDate
}).FirstOrDefault(x => x.Id == id));
usage :
public Orders GetOrderByIdCompiled(int id)
{
return _getOrderById(_context, id);
}
چه زمانی از این ویژگی استفاده کنیم ؟1-کوئری تان قرار است خیلی بیشتر از یک بار متوالی اجرا شود.
2-کوئری شما به قدر کافی پیچیده است و هزینه هربار کامپایل ان زیاد است.
* نکته اول اگر دلیگیت کامپایل کوئری مورد نظر خود را به صورت استاتیک تعریف کنید می توانید در تمام نمونه های ApplicationDbContext خود از آن استفاده کنید.
*نکته دوم نسخه جاری Ef Core هنوز نوع خروجی
List<T>را برای یک کامپل کوئری پشتیبانی نمیکند.
@fullStackDevs
#High_Performance
#EfCore_Best_Practice
#DbContext_pooling
🔸 در این پست به معرفی یک روش جدید Register کردن DbContext به Di Container در متد ConfigureServices در کلاس Startup می پردازیم.
ابتدایی ترین و ساده ترین روش که برای Register کردن custom DbContext خود به سیستم dependency injection استفاده میکنیم تا بعدا نمونه ای از custom DbContext خود به صورت constructor parameters و یا دیگر روش های دریافت Instance از DI، دریافت کنیم روش زیر است :
در نسخه 2.0 از Ef Core روش جدید برای Register کردن DbContext به سیستم dependency injection معرفی شد که همانطور که در مثال بعدی خواهید به صورت شفاف مجموعه ای از موارد DbContext قابل استفاده مجدد را ارائه می دهد.
در نهایت هنگامی که Request پردازش شد و کار ان با نمونه دریافت شده DbContext تمام شد، Ef تمامیه State های قابل ردیابی DbContext را که از آنها آگاه هست را reset کرده و DbContext inctance دوباره به Context Pool بر میگردد.
این روال از نظر مفهومی شبیه connection pooling در Ado.net است و از مزیت های آن میتوان به کاهش هزینه ساخت DbContext instance اشاره کرد.
استفاده از این متد البته باعث محدودیت های اندکی در متد OnConfiguring() در DbContext میشود.
🔻 نکته بسیار مهم
نکته مهم این است که اگر به صورت Custom مکانیزمی را در derived DbContext class خود پیاده کرده باشید که باعث نگه داری state ای شود و از انجایی که Ef core فقط state هایی که از آنها اگاه هست را reset میکند پس در نتیجه state که شما به صورت custom ایجاد کرده اید در DbContext instance باقی میماند و باعث share شدن آن در بین درخواست ها میشود.
@fullStackDevs
#EfCore_Best_Practice
#DbContext_pooling
🔸 در این پست به معرفی یک روش جدید Register کردن DbContext به Di Container در متد ConfigureServices در کلاس Startup می پردازیم.
ابتدایی ترین و ساده ترین روش که برای Register کردن custom DbContext خود به سیستم dependency injection استفاده میکنیم تا بعدا نمونه ای از custom DbContext خود به صورت constructor parameters و یا دیگر روش های دریافت Instance از DI، دریافت کنیم روش زیر است :
services.AddDbContext<
BloggingContext
>(options => options.UseSqlServer("ConnectionString"));
🔹 که Register کردن DbContext به این طریق به معنی ساختن یک instance جدید از DbContext برای هر Request میباشد که مطمئنا روال Instance سازی از DbContext هزینه هایی برای اپلیکیشن دارد.در نسخه 2.0 از Ef Core روش جدید برای Register کردن DbContext به سیستم dependency injection معرفی شد که همانطور که در مثال بعدی خواهید به صورت شفاف مجموعه ای از موارد DbContext قابل استفاده مجدد را ارائه می دهد.
services.AddDbContextPool<BloggingContext>(
options => options.UseSqlServer(
ConnectionString
));▪️ اگر از این متد برای Register کردن DbContext استفاده کنید زمانیه که در اپلیکیشن درخواست نمونه ای جدید از DbContext داده شود ابتدا در Context Pool چک میشود که ایا نمونه ای از DbContext وجود دارد و اگر نمونه ای وجو داشت،در اختیار درخواست دهنده قرار میدهد.
در نهایت هنگامی که Request پردازش شد و کار ان با نمونه دریافت شده DbContext تمام شد، Ef تمامیه State های قابل ردیابی DbContext را که از آنها آگاه هست را reset کرده و DbContext inctance دوباره به Context Pool بر میگردد.
این روال از نظر مفهومی شبیه connection pooling در Ado.net است و از مزیت های آن میتوان به کاهش هزینه ساخت DbContext instance اشاره کرد.
استفاده از این متد البته باعث محدودیت های اندکی در متد OnConfiguring() در DbContext میشود.
🔻 نکته بسیار مهم
نکته مهم این است که اگر به صورت Custom مکانیزمی را در derived DbContext class خود پیاده کرده باشید که باعث نگه داری state ای شود و از انجایی که Ef core فقط state هایی که از آنها اگاه هست را reset میکند پس در نتیجه state که شما به صورت custom ایجاد کرده اید در DbContext instance باقی میماند و باعث share شدن آن در بین درخواست ها میشود.
@fullStackDevs
Forwarded from Web Devs
#High_Performance
#EfCore_Best_Practice
#DbContext_pooling
🔸 در این پست به معرفی یک روش جدید Register کردن DbContext به Di Container در متد ConfigureServices در کلاس Startup می پردازیم.
ابتدایی ترین و ساده ترین روش که برای Register کردن custom DbContext خود به سیستم dependency injection استفاده میکنیم تا بعدا نمونه ای از custom DbContext خود به صورت constructor parameters و یا دیگر روش های دریافت Instance از DI، دریافت کنیم روش زیر است :
در نسخه 2.0 از Ef Core روش جدید برای Register کردن DbContext به سیستم dependency injection معرفی شد که همانطور که در مثال بعدی خواهید به صورت شفاف مجموعه ای از موارد DbContext قابل استفاده مجدد را ارائه می دهد.
در نهایت هنگامی که Request پردازش شد و کار ان با نمونه دریافت شده DbContext تمام شد، Ef تمامیه State های قابل ردیابی DbContext را که از آنها آگاه هست را reset کرده و DbContext inctance دوباره به Context Pool بر میگردد.
این روال از نظر مفهومی شبیه connection pooling در Ado.net است و از مزیت های آن میتوان به کاهش هزینه ساخت DbContext instance اشاره کرد.
استفاده از این متد البته باعث محدودیت های اندکی در متد OnConfiguring() در DbContext میشود.
🔻 نکته بسیار مهم
نکته مهم این است که اگر به صورت Custom مکانیزمی را در derived DbContext class خود پیاده کرده باشید که باعث نگه داری state ای شود و از انجایی که Ef core فقط state هایی که از آنها اگاه هست را reset میکند پس در نتیجه state که شما به صورت custom ایجاد کرده اید در DbContext instance باقی میماند و باعث share شدن آن در بین درخواست ها میشود.
@fullStackDevs
#EfCore_Best_Practice
#DbContext_pooling
🔸 در این پست به معرفی یک روش جدید Register کردن DbContext به Di Container در متد ConfigureServices در کلاس Startup می پردازیم.
ابتدایی ترین و ساده ترین روش که برای Register کردن custom DbContext خود به سیستم dependency injection استفاده میکنیم تا بعدا نمونه ای از custom DbContext خود به صورت constructor parameters و یا دیگر روش های دریافت Instance از DI، دریافت کنیم روش زیر است :
services.AddDbContext<
BloggingContext
>(options => options.UseSqlServer("ConnectionString"));
🔹 که Register کردن DbContext به این طریق به معنی ساختن یک instance جدید از DbContext برای هر Request میباشد که مطمئنا روال Instance سازی از DbContext هزینه هایی برای اپلیکیشن دارد.در نسخه 2.0 از Ef Core روش جدید برای Register کردن DbContext به سیستم dependency injection معرفی شد که همانطور که در مثال بعدی خواهید به صورت شفاف مجموعه ای از موارد DbContext قابل استفاده مجدد را ارائه می دهد.
services.AddDbContextPool<BloggingContext>(
options => options.UseSqlServer(
ConnectionString
));▪️ اگر از این متد برای Register کردن DbContext استفاده کنید زمانیه که در اپلیکیشن درخواست نمونه ای جدید از DbContext داده شود ابتدا در Context Pool چک میشود که ایا نمونه ای از DbContext وجود دارد و اگر نمونه ای وجو داشت،در اختیار درخواست دهنده قرار میدهد.
در نهایت هنگامی که Request پردازش شد و کار ان با نمونه دریافت شده DbContext تمام شد، Ef تمامیه State های قابل ردیابی DbContext را که از آنها آگاه هست را reset کرده و DbContext inctance دوباره به Context Pool بر میگردد.
این روال از نظر مفهومی شبیه connection pooling در Ado.net است و از مزیت های آن میتوان به کاهش هزینه ساخت DbContext instance اشاره کرد.
استفاده از این متد البته باعث محدودیت های اندکی در متد OnConfiguring() در DbContext میشود.
🔻 نکته بسیار مهم
نکته مهم این است که اگر به صورت Custom مکانیزمی را در derived DbContext class خود پیاده کرده باشید که باعث نگه داری state ای شود و از انجایی که Ef core فقط state هایی که از آنها اگاه هست را reset میکند پس در نتیجه state که شما به صورت custom ایجاد کرده اید در DbContext instance باقی میماند و باعث share شدن آن در بین درخواست ها میشود.
@fullStackDevs