اشتراک‌ها
معرفی Orleans 3.0

Major changes since Orleans 2.0

Distributed ACID transactions — multiple grains can join a transaction regardless of where their state is stored
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 

معرفی Orleans 3.0
اشتراک‌ها
پشتیبانی Clang از ویندوز و کامپایل Chrome برای Windows توسط آن

Google has helped with the open source project to make Clang Windows compatible. Not only is it Windows compatible, but it is also binary compatible with output from the Microsoft compiler. This means you can use the linker to join up code from each compiler into a single program. 

پشتیبانی Clang از ویندوز و کامپایل Chrome برای Windows توسط آن
اشتراک‌ها
ویدیوهای منتشر شده درباره Microsoft Edge - مرورگر جدید مایکروسافت
 Join the team behind Microsoft Edge as we present the latest updates to our roadmap, the EdgeHTML rendering engine, and the Chakra JavaScript engine. Then enjoy our fantastic lineup of guest speakers as they share their expertise on modern web technologies like ES6, SVG, WebGL and WebAudio. 
ویدیوهای منتشر شده درباره  Microsoft Edge - مرورگر جدید مایکروسافت
نظرات مطالب
ایجاد یک Repository در پروژه برای دستورات EF
IQueryable فقط یک expression است. هنوز اجرا نشده. (expose آن از طریق وب سرویس اشتباه است و به مشکلات serialization برخواهید خورد.)
زمانیکه ToList، First و امثال آن روی این عبارت فراخوانی شود تبدیل به SQL شده و سپس بر روی بانک اطلاعاتی اجرا می‌شود. به این deferred execution یا اجرای به تعویق افتاده گفته می‌شود.
اگر این عبارت را در اختیار لایه‌های دیگر قرار دهید، یعنی انتهای کار را بازگذاشته‌اید و حد و حدود سیستم شما مشخص نیست. شما اگر IQueryable بازگشت دهید، در لایه‌ای دیگر می‌شود یک join روی آن نوشت و اطلاعات چندین جدول دیگر را استخراج کرد؛ درحالیکه نام متد شما GetUsers بوده. بنابراین بهتر است به صورت صریح اطلاعات را به شکل List بازگشت دهید، تا انتهای کار باز نمانده و طراحی شما نشتی نداشته باشد.
مطالب
آشنایی با SplitQuery در EF Core 5x
در دیتابیس‌های رابطه‌ای، داده‌ها(رکوردها)ی مرتبط، با استفاده از Join بدست آورده می‌شوند و بعضا نیاز هست برای رسیدن به یک داده‌ی مورد نیاز، باید چندین Join بین جداول مختلف به کار برده شود. در Entity Framework ، زمانیکه قصد بدست آوردن داده‌های مرتبط را داریم، از Include  استفاده می‌کنیم که در نهایت منجر به همان left Join می‌شود.
برای درک بهتر و توضیح راحت‌تر، فرض کنید بر روی دیتابیس سایت جاری، قصد داریم لیست هر کاربر را به همراه مقالاتی که در سایت منتشر کرده‌است، بدست بیاوریم. برای اینکار قطعه کد زیر را خواهیم داشت :
  var users = context.Users.Include(x => x.Articles).ToList();
دستور فوق، منجر به تولید T-SQL زیر خواهد شد:
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 موارد زیر مطرح می‌باشد :

  • زمانیکه کوئری تبدیل به دو یا چند کوئری می‌شود، ممکن است بعد از اجرا کوئری اول و قبل از اجرای کوئری دوم، یک به روزرسانی انجام شود که ممکن است consistency نقض شود.
  • در این حالت، چندین درخواست و رفت و برگشت اجرا می‌شود که همین می‌تواند باعث تاخیر و افزایش زمان گردد.
مطالب
ارتباط بین کامپوننت‌ها در Vue.js - قسمت سوم استفاده از تزریق وابستگی‌ها
در قسمت‌های قبلی( ^ و ^) نحوه‌ی ارتباط بین کامپوننت‌ها در Vue.js بررسی و مزایا و معایب آنها بیان شد. روش دیگری هم برای ارسال اطلاعات از کامپوننتِ Parent به فرزندانش وجود دارد که با استفاده از Dependency Injection یا به اختصار DI مقدور می‌باشد و در ورژن +2.2 معرفی شد که نحوه‌ی ارتباط بین کامپوننتِ Parent و فرزندانش را آسان نمود. پیش‌تر برای ارتباط از Parent به Child، از Props استفاده میکردیم، ولی اگر قرار بود در چند سطح این ارتباط عمیق باشد، باز هم مدیریت کردن Props مشکل و سخت بود. اکنون با استفاده از provide و inject قادر خواهیم بود تا آبجکت، فانکشن و یا دیتایِ یک کامپوننتِ Parent را در فرزندانش فراخوانی و استفاده کنیم. اگر در حالت عادی نیاز بود تا در دو سطح، یا بیشتر (مانند تصویر زیر) دیتایِ کامپوننت پدر را به فرزند، نوه و ... انتقال دهیم، می‌بایست اطلاعات را بصورت Props به هر Level انتقال دهیم.



روش جاری شباهت زیادی به استفاده از Context در React دارد:

Context provides a way to pass data through the component tree without having to pass props down manually at every level


جهت به اشتراک گذاری دیتا یا تابعی در کامپوننت Parent با Children، به شکل زیر عمل میکنیم. در اینجا با استفاده از provide، دیتای foo به اشتراک گذاشته شده‌است:
// parent component providing 'foo'
var Provider = {
  provide: {
    foo: 'bar'
  },
  // ...
}
و در کامپوننت‌های فرزند به شکل زیر میتوانیم مقدار foo را دریافت کنیم:
// child component injecting 'foo'
var Child = {
  inject: ['foo'],
  created () {
    console.log(this.foo) // => "bar"
  }
  // ...
}

میتوانیم مقدار پیش فرض دیتایِ ارسالی از کامپوننت Parent را در قسمت data و props در کامپوننت Child دریافت نماییم:
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
    }
  }
}

نکته: در این روش در صورتیکه دیتایِ به اشتراک گذاشته شده در کامپوننتِ Parent تغییر کند، مقدار آن در کامپوننت Child تغییری نخواهد کرد و مانند روش‌های قبلی (^ و ^) نیست و نیاز به نوشتن کدی برای تعامل داشتن و به‌روز رسانی مقادیر، در کامپوننت Child می‌باشد.
کد زیر  را در نظر بگیرید؛ با زدن دکمه‌ی Increment counter  مقدار counter در کامپوننتِParent تغییر میکند، ولی در کامپوننت Child، مقدار counter_in_child  تغییری حاصل نمی‌کند.
<!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>
       
برای اینکه بتوان تغییرات ایجاد شده‌ی بر روی دیتا را در کامپوننتِChild، مشاهده کرد، نیاز داریم کد زیر را در قسمت provide به ازای آن دیتا اضافه کنیم: 
<!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>

مثالی از نحوه به اشتراک گذاری متد بین Parent و Child.

نتیجه گیری:
A) استفاده از این روش مرسوم نیست و بیشتر برای ساخت پلاگین در Vuejs مورد استفاده قرار میگیرد:
provide  and  inject  are primarily provided for advanced plugin / component library use cases. It is NOT recommended to use them in generic application code
B) برای استفاده از این روش کتابخانه‌هایی جهت ساده‌تر کردن بکارگیری ایجاد شده‌است.
C) این روش برای ارتباط  Sibling Component مناسب نیست.
نظرات مطالب
امکان تعریف اعضای static abstract در اینترفیس‌های C# 11
اضافه شدن Generic Parsing به دات نت 7

تا قبل از دات نت 7، متدهای Parse و TryParse جزو استاندارد اغلب نوع‌ها در دات نت بودند؛ اما امکان استفاده‌ی جنریک از آن‌ها وجود نداشت. این مشکل به لطف وجود اعضای استاتیک اینترفیس‌ها در دات نت 7 و C# 11 برطرف شده‌است. برای این منظور دو اینترفیس جدید System.IParsable و System.ISpanParsable به دات نت 7 اضافه شده‌اند که امکان دسترسی به متد T.Parse را میسر می‌کنند.
دو نمونه مثال از نحوه‌ی استفاده‌ی از این API جدید را در ادامه مشاهده می‌کنید:
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));
}
اگر می‌خواستیم متد ParseIt را به صورت جنریک و بدون استفاده از ویژگی‌های جدید زبان #C و دسترسی مستقیم به T.Parse بنویسیم، یک روش آن، استفاده از Reflection به صورت زیر می‌بود:
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 })!;
}