Major changes since Orleans 2.0
A new scheduler, which alone increased performance by over 30% in some cases
A new code generator based on Roslyn code analysis
Rewritten cluster membership for improved recovery speed
Co-hosting support
var users = context.Users.Include(x => x.Articles).ToList();
SELECT [u].[Id], [u].[FirstName], [u].[LastName], [a].[Id], [a].[Approved], [a].[AuthorId], [a].[Body], [a].[PubDate], [a].[Subject] FROM [Users] AS [u] LEFT JOIN [Articles] AS [a] ON [u].[Id] = [a].[AuthorId] ORDER BY [u].[Id], [a].[Id]
شکل یک
همانطور که در عکس فوق مشاهده میکنید، کاربر با شناسهی 1، ده مقاله را منتشر کردهاست که به ازای تعداد مقالات، سه فیلد شناسه کاربر، نام و نام خانوادگی، تکرار شدهاست و همین اتفاق برای کاربر با شناسهی 2 هم تکرار شدهاست. قطعا در اکثر نرم افزارها، نیاز به چنین کوئریها و دادههایی زیاد است و جلوگیری از این تکرار دادهها، میتواند بر روی کارایی نرم افزار تاثیر گذار باشد.
Cartesian explosion
اجرای یک Join بین جداول با رابطهی one to many، منجر به تکرار ستونهای جدول طرف one، به تعداد رکوردهای مرتبط میشود. این اتفاق باعث هدر رفت منابع و همچنین کند شدن اجرای کوئری خواهد شد که این مشکل تحت عنوان Cartesian explosion problem شناخته میشود.
از نسخه EF Core5.0، امکانی اضافه شدهاست که کمک میکند این مشکل را برطرف کنیم و سرعت اجرای کوئریها سریعتر شود. Entity Framework به صورت پیش فرض، کوئریها را در قالب یک دستور (یک رفت و برگشت) انجام میدهد، اما میتوان این رفتار را با استفاده از قابلیت SplitQuery تغییر داد.
متد ()SplitQuery
با استفاده از این متد، به Entity Framework الزام میکنیم که بجای استفاده از Join در یک کوئری، کوئریهای جداگانهای را بر روی دیتابیس اجرا کند. برای کوئری اول که در بالا نوشتیم، به صورت زیر میتوانیم SplitQuery را اعمال کنیم:
var users = context.Users.AsSplitQuery().Include(x => x.Articles).ToList();
کوئری حاصل از کد فوق به صورت زیر میباشد:
-- First Part SELECT [u].[Id], [u].[FirstName], [u].[LastName] FROM [Users] AS [u] ORDER BY [u].[Id] -- Second Part SELECT [a].[Id], [a].[Approved], [a].[AuthorId], [a].[Body], [a].[PubDate], [a].[Subject], [u].[Id] FROM [Users] AS [u] INNER JOIN [Articles] AS [a] ON [u].[Id] = [a].[AuthorId] ORDER BY [u].[Id]
همانطور که مشاهده میکنید، دو کوئری تولید شده است که کوئری اول برای دریافت لیست کاربران و کوئری دوم برای لیست مقالات تولید شدهاست. این تغییر باعث شدهاست که فیلدهای مورد نیاز از جدول کاربران، به تعداد مقالات هر کاربر تکرار نشود.
شکل 2- خروجی حاصل بعد از اجرا به صورت SplitQuery
فعال سازی به صورت سراسری
همانطور که بیان شد، EF به صورت پیش فرض کوئریها را در قالب یک درخواست اجرا میکند. اگر تمایل دارید خاصیت SplitQuery بر روی تمامی کوئریها اعمال شود، میتوانید به صورت زیر این امکان را به صورت سراسری اعمال نمایید.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder .UseSqlServer( @"Server=(localdb)\mssqllocaldb;Database=EFQuerying;", o => o.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery)); }
اگر SplitQuery را به صورت سراسری فعال کردید و نیاز داشتید جایی یک کوئری را به همان روش SignleQuery اجرا کنید، میتوانید از متد SingleQuery به صورت زیر استفاده نمایید.
var users = context.Users.AsSingleQuery().Include(x => x.Articles).ToList();
عکس زیر مقایسه ای بین اجرای کوئریها به صورت Single و Split میباشد:
مبنع: thinktecture
در رابطه با SplitQuery موارد زیر مطرح میباشد :
روش جاری شباهت زیادی به استفاده از Context در React دارد:
Context provides a way to pass data through the component tree without having to pass props down manually at every level
// parent component providing 'foo' var Provider = { provide: { foo: 'bar' }, // ... }
// child component injecting 'foo' var Child = { inject: ['foo'], created () { console.log(this.foo) // => "bar" } // ... }
Using an injected value as the default for a prop //دریافت میکنیم props در قسمت child را در کامپوننت foo مقدار const Child = { inject: ['foo'], props: { bar: { default () { return this.foo } } } } Using an injected value as data entry //دریافت میکنیم data در قسمت child را در کامپوننت foo مقدار const Child = { inject: ['foo'], data () { return { bar: this.foo } } }
<!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <script src="https://cdn.jsdelivr.net/npm/vue"></script> <title>Dependency injection</title> </head> <body> <div id="app"> <button @click="counter++">Increment counter</button> <h2>Parent</h2> <p>{{counter}}</p> <div> <h3>Child</h3> <child></child> </div> </div> <script> const Child = { inject: ['counter_in_child'], template: `<div>Counter Child is:{{ counter_in_child }}</div>` }; new Vue ({ el: "#app", components: { Child }, provide() { return { counter_in_child: this.counter }; }, data() { return { counter: 0 }; } }); </script> </body> </html>
<!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <script src="https://cdn.jsdelivr.net/npm/vue"></script> <title>Dependency injection</title> </head> <body> <div id="app"> <button @click="counter++">Increment counter</button> <h2>Parent</h2> <p>{{counter}}</p> <div> <h3>Child</h3> <child></child> </div> </div> <script> const Child = { inject: ['counter_in_child'], template: `<div>Counter Child is:{{ counter_in_child.counter }}</div>` }; new Vue ({ el: "#app", components: { Child }, provide() { const counter_in_child={}; Object.defineProperty(counter_in_child,'counter',{ enumerable:true, get:()=>this.counter }) return { counter_in_child }; }, data() { return { counter: 0 }; } }); </script> </body> </html>
provide
and inject
are primarily provided for advanced plugin / component library use cases. It is NOT recommended to use them in generic application code public static T ParseIt<T>(string content, IFormatProvider? provider) where T : IParsable<T> { return T.Parse(content, provider); } public IEnumerable<T> ParseCsvRow<T>(string content, IFormatProvider? provider) where T : IParsable<T> { return content.Split(',').Select(str => T.Parse(str, provider)); }
public static T ParseIt<T>(string content, IFormatProvider? provider) { var type = typeof(T); var method = type.GetMethod("Parse", BindingFlags.Static | BindingFlags.Public, new[] { typeof(string), typeof(IFormatProvider) }); return (T)method!.Invoke(null, new object?[] { content, provider })!; }