نگاهی به ویژگی های جدید 6 #C
The C# language itself has changed little in version 6, the main importance of the release being the introduction of the Roslyn .NET Compiler Platform. However the New features and improvements that have been made to C# are welcome because they are aimed at aiding productivity. Paulo Morgado explains what they are, and how to use them.
پیشنیازهای این سری
در این سری از بانک اطلاعاتی استاندارد مثال به همراه SQL Server 2016، به نام WideWorldImporters استفاده میکنیم. برای دریافت آن، به قسمت releases مثالهای مایکروسافت مراجعه کرده و فایل WideWorldImporters-Full.bak را دریافت کنید. پس از دریافت این فایل، برای restore سریع آن، میتوانید دستور زیر را اجرا کنید که در آن باید مسیر فایل bak دریافتی و همچنین مسیر ایجاد فایلهای mdf/ldf/ndf را مطابق مسیرهای سیستم خودتان اصلاح نمائید (فقط مسیر پوشهها را نیاز است تغییر دهید):
use master; RESTORE DATABASE WideWorldImporters FROM disk='D:\path\WideWorldImporters-Full.bak' WITH MOVE 'WWI_Primary' TO 'D:\SQL_Data\WideWorldImporters.mdf', MOVE 'WWI_Log' TO 'D:\SQL_Data\WideWorldImporters_log.ldf', MOVE 'WWI_UserData' TO 'D:\SQL_Data\WideWorldImporters_UserData.ndf', MOVE 'WWI_InMemory_Data_1' TO 'D:\SQL_Data\WideWorldImporters_InMemory_Data_1'
یافتن اطلاعاتی در مورد کوئریها
SQL Server زمانیکه یک کوئری را اجرا میکند، اطلاعاتی را نیز به همراه آن تولید خواهد کرد که سبب ایجاد یک Query Plan میشود و در آن، اطلاعاتی مانند جداول مورد استفاده، نوع جوینها، ایندکسهای استفاده شده و غیره وجود دارند. علاوه بر آن، Query Statistics نیز قابل دسترسی هستند که در آن مدت زمان اجرای یک کوئری، میزان I/O صورت گرفته و میزان مصرف CPU کوئری، ذکر میشوند. برای دسترسی یافتن به این اطلاعات، میتوان به اشیاء مختلف SQL Server مراجعه کرد؛ مانند dynamic management objects یا به اختصار DMO's، همچنین extended events، traces، query stores و یا حتی management studio. مهمترین تفاوت اینها نیز در نحوهی دسترسی به اطلاعات آنها است که میتواند زنده (live) و یا ذخیره شده در جائی باشند. در اینجا تنها منبعی که امکان مشاهدهی این اطلاعات را به صورت زنده میسر میکند، management studio است. البته live در اینجا به معنای امکان مشاهدهی تمام اطلاعات مرتبط با یک کوئری، مانند آمار و کوئری پلن آن در داخل محیط management studio، پس از اجرای یک کوئری است. در این قسمت بیشتر به روش استخراج اطلاعات آماری کوئریهای زنده میپردازیم و در قسمتهای بعدی، سایر گزینههای نامبرده شده را نیز بررسی خواهیم کرد.
مشاهدهی زندهی دادههای مرتبط با اجرای یک کوئری در management studio
پس از restore بانک اطلاعاتی مثال WideWorldImporters که عنوان شد، در برنامهی Microsoft SQL Server Management Studio، کوئری زیر را اجرا میکنیم:
USE [WideWorldImporters]; GO SELECT [s].[StateProvinceName], [s].[SalesTerritory], [s].[LatestRecordedPopulation], [s].[StateProvinceCode] FROM [Application].[Countries] [c] JOIN [Application].[StateProvinces] [s] ON [s].[CountryID] = [c].[CountryID] WHERE [c].[CountryName] = 'United States'; GO
اینجا است که نیاز به اطلاعات بیشتری در مورد نحوهی اجرای این کوئری داریم. برای استخراج این اطلاعات، اینبار گزینههای تولید و جمع آوری اطلاعات آماری IO و TIME را روشن میکنیم و سپس همان کوئری قبلی را اجرا خواهیم کرد:
USE [WideWorldImporters]; GO SET STATISTICS IO ON; GO SET STATISTICS TIME ON; GO SELECT [s].[StateProvinceName], [s].[SalesTerritory], [s].[LatestRecordedPopulation], [s].[StateProvinceCode] FROM [Application].[Countries] [c] JOIN [Application].[StateProvinces] [s] ON [s].[CountryID] = [c].[CountryID] WHERE [c].[CountryName] = 'United States'; GO
SQL Server parse and compile time: CPU time = 0 ms, elapsed time = 504 ms. (53 rows affected) Table 'Countries'. Scan count 0, logical reads 118, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. Table 'StateProvinces'. Scan count 1, logical reads 43, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. SQL Server Execution Times: CPU time = 0 ms, elapsed time = 10 ms.
استخراج اطلاعات Actual Execution Plan یک کوئری
کوئری را زیر با فرض IO ON و TIME ON حاصل از اجرای کوئری قبل، اجرا میکنیم:
USE [WideWorldImporters]; GO SET STATISTICS XML ON; GO SELECT [s].[StateProvinceName], [s].[SalesTerritory], [s].[LatestRecordedPopulation], [s].[StateProvinceCode] FROM [Application].[Countries] [c] JOIN [Application].[StateProvinces] [s] ON [s].[CountryID] = [c].[CountryID] WHERE [c].[CountryName] = 'United States'; GO SET STATISTICS XML OFF; GO
SQL Server parse and compile time: CPU time = 0 ms, elapsed time = 0 ms. SQL Server Execution Times: CPU time = 0 ms, elapsed time = 0 ms. SQL Server parse and compile time: CPU time = 0 ms, elapsed time = 0 ms. SQL Server Execution Times: CPU time = 0 ms, elapsed time = 0 ms. SQL Server parse and compile time: CPU time = 0 ms, elapsed time = 7 ms. (53 rows affected) Table 'Countries'. Scan count 0, logical reads 118, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. Table 'StateProvinces'. Scan count 1, logical reads 43, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. (1 row affected) SQL Server Execution Times: CPU time = 15 ms, elapsed time = 179 ms. SQL Server parse and compile time: CPU time = 0 ms, elapsed time = 0 ms. SQL Server Execution Times: CPU time = 0 ms, elapsed time = 0 ms.
اگر بر روی این XML کلیک کنیم، برگهی جدید نمایش گرافیکی این plan ظاهر میشود:
با کلیک راست بر روی این برگه، میتوان اطلاعات آنرا جهت بررسیهای بعدی و یا به اشتراک گذاری آن ذخیره کرد.
در این plan اگر اشارهگر ماوس را بر روی هر کدام از عناصر آن حرکت دهیم، اطلاعاتی مانند actual number of rows نیز مشاهده میشود، در کنار اطلاعات تخمینی؛ به همین جهت به آن Actual Execution Plan هم گفته میشود.
این یک روش دسترسی به Execution Plan است. روش دوم آن با استفاده از امکانات رابط کاربری خود Management Studio است؛ با فشردن دکمههای Ctrl+M و یا انتخاب گزینهی Include actual execution plan از منوی Query آن. پس از آن کوئری زیر را اجرا کنید:
SET STATISTICS IO ON; GO SET STATISTICS TIME ON; GO SELECT [s].[StateProvinceName], [s].[SalesTerritory], [s].[LatestRecordedPopulation], [s].[StateProvinceCode] FROM [Application].[Countries] [c] JOIN [Application].[StateProvinces] [s] ON [s].[CountryID] = [c].[CountryID] WHERE [c].[CountryName] = 'United States'; GO
استخراج اطلاعات Estimated Execution Plan یک کوئری
تا اینجا نحوهی استخراج اطلاعات Actual Execution Plan را بررسی کردیم که به همراه اطلاعات دقیق حاصل از اجرای کوئری نیز بود؛ مانند actual number of rows. نوع دیگری از Execution Planها را نیز میتوان از SQL Server درخواست کرد که به آنها Estimated Execution Plan گفته میشود و حاصل اجرای کوئری نیستند؛ بلکه تخمینی هستند از روش اجرای این کوئری توسط SQL Server. برای فعالسازی محاسبهی آن، ابتدا کوئری زیر را در management studio انتخاب کنید:
USE [WideWorldImporters]; GO SELECT [s].[StateProvinceName], [s].[SalesTerritory], [s].[LatestRecordedPopulation], [s].[StateProvinceCode] FROM [Application].[Countries] [c] JOIN [Application].[StateProvinces] [s] ON [s].[CountryID] = [c].[CountryID] WHERE [c].[CountryName] = 'United States'; GO
همانطور که مشاهده میکنید، اینبار نتیجهی حاصل، به همراه اطلاعاتی مانند actual number of rows نیست و صرفا تخمینی است از روش اجرای این کوئری، توسط SQL Server.
جمع آوری اطلاعات آماری کلاینتها
در منوی Query، گزینهای تحت عنوان Include client statistics نیز وجود دارد. با انتخاب آن، اگر کوئری زیر را اجرا کنیم:
USE [WideWorldImporters]; GO SELECT [s].[StateProvinceName], [s].[SalesTerritory], [s].[LatestRecordedPopulation], [s].[StateProvinceCode] FROM [Application].[Countries] [c] JOIN [Application].[StateProvinces] [s] ON [s].[CountryID] = [c].[CountryID] WHERE [c].[CountryName] = 'United States'; GO
در اینجا مشخص میشود که آیا عملیات insert/update/delete انجام شدهاست. چه تعداد ردیف تحت تاثیر اجرای این کوئری قرار گرفتهاند. چه تعداد تراکنش انجام شدهاست. همچنین اطلاعات آماری شبکه و زمان نیز در اینجا ارائه شدهاند.
در همین حالت، کوئری جدید زیر را با تغییر قسمت where کوئری قبلی، اجرا کنید:
SELECT [s].[StateProvinceName], [s].[SalesTerritory], [s].[LatestRecordedPopulation], [s].[StateProvinceCode] FROM [Application].[Countries] [c] JOIN [Application].[StateProvinces] [s] ON [s].[CountryID] = [c].[CountryID] WHERE [s].[StateProvinceName] LIKE 'O%'; GO
در اینجا حداکثر 10 کوئری را میتوان با هم مقایسه کرد و بیشتر از آن سبب حذف موارد قدیمی از لیست میشود.
عدم نمایش ردیفهای بازگشت داده شدهی توسط کوئری در حین جمع آوری اطلاعات آماری
هربار اجرای یک کوئری در management studio، به همراه بازگشت و نمایش ردیفهای مرتبط با آن کوئری نیز میباشد. اگر میخواهید در حین بررسی کارآیی کوئریها از نمایش این ردیفها صرف نظر کنید (تا بار این برنامه کاهش یابد)، میتوانید از منوی Query، گزینهی Query Options را انتخاب کرده و در قسمت Results، گزینهی Grid آن، گزینهی discard results after execution را انتخاب کنید تا دیگر برگهی results نمایش داده نشود و وقت و منابع را تلف نکند. بدیهی است پس از پایان کار بررسی آماری، نیاز به عدم انتخاب این گزینه خواهد بود.
In this section, I’m going to cover how you can use SignalR outside of a Hub. In most asp.net core applications, you will likely want to communicate with the connect clients from within your application but outside of a Hub. You can accomplish this by using the HubContext.
For example, an ASP.NET Core MVC Controller or any other class that is instantiated by ASP.NET Core’s Dependency Injection.
The HubContext allows you to send messages to your connected clients. It has many of the same features to communicate with clients as when you are inside of a Hub.
Protocol Buffers are a language-neutral, platform-neutral, extensible way of serializing structured data for use in communications protocols, data storage, and more, originally designed at Google (see).
protobuf.js is a pure JavaScript implementation with TypeScript support for node.js and the browser. It's easy to use, blazingly fast and works out of the box with .proto files!
تهیه یک بانک اطلاعاتی نمونه
برای نمایش امکانات کار با روش Database first، نیاز است یک بانک اطلاعاتی را به صورت مستقل و متداولی ایجاد کنیم. به همین جهت اسکریپت SQL ذیل را توسط Management studio اجرا کنید تا بانک اطلاعاتی BloggingCore2016، به همراه دو جدول به هم وابسته، در آن ایجاد شوند:
CREATE DATABASE [BloggingCore2016] GO USE [BloggingCore2016] GO CREATE TABLE [Blog] ( [BlogId] int NOT NULL IDENTITY, [Url] nvarchar(max) NOT NULL, CONSTRAINT [PK_Blog] PRIMARY KEY ([BlogId]) ); GO CREATE TABLE [Post] ( [PostId] int NOT NULL IDENTITY, [BlogId] int NOT NULL, [Content] nvarchar(max), [Title] nvarchar(max), CONSTRAINT [PK_Post] PRIMARY KEY ([PostId]), CONSTRAINT [FK_Post_Blog_BlogId] FOREIGN KEY ([BlogId]) REFERENCES [Blog] ([BlogId]) ON DELETE CASCADE ); GO INSERT INTO [Blog] (Url) VALUES ('https://www.dntips.ir/'), ('http://blogs.msdn.com/dotnet'), ('http://blogs.msdn.com/webdev'), ('http://blogs.msdn.com/visualstudio') GO
پیشنیازهای مهندسی معکوس ساختار بانک اطلاعاتی در EF Core
در قسمت اول در حین بررسی «برپایی تنظیمات اولیهی EF Core 1.0 در یک برنامهی ASP.NET Core 1.0»، چهار مدخل جدید را به فایل project.json برنامه اضافه کردیم. مدخل جدید Microsoft.EntityFrameworkCore.Tools که به قسمت tools آن اضافه شد، پیشنیاز اصلی کار با EF Core Migrations است. همچنین وجود مدخل Microsoft.EntityFrameworkCore.SqlServer.Design برای تدارک امکانات مهندسی معکوس ساختار یک بانک اطلاعاتی SQL Server ضروری است.
تبدیل ساختار دیتابیس BloggingCore2016 به کدهای معادل EF Core آن
پس از فعال سازی ابزارهای خط فرمان EF Core، به پوشهی اصلی پروژه مراجعه کرده، کلید shift را نگه دارید. سپس کلیک راست کرده و گزینهی Open command window here را انتخاب کنید تا خط فرمان از این پوشه آغاز شود. در ادامه دستور ذیل را صادر کنید:
dotnet ef dbcontext scaffold "Data Source=(local);Initial Catalog=BloggingCore2016;Integrated Security = true" Microsoft.EntityFrameworkCore.SqlServer -o Entities --context MyDBDataContext --verbose
اجرا این دستور سبب اتصال به رشتهی اتصالی ذکر شده که به بانک اطلاعاتی BloggingCore2016 اشاره میکند، میشود. سپس پروایدر مدنظر ذکر شدهاست. سوئیچ o محل درج فایلهای نهایی را مشخص میکند. برای مثال در اینجا فایلهای نهایی مهندسی معکوس شده در پوشهی Entities درج میشوند (تصویر فوق). همچنین در اینجا امکان ذکر فایل context تولیدی نیز وجود دارد. اگر علاقمند باشید تا تمام ریز جزئیات این عملیات را نیز مشاهده کنید، میتوانید پارامتر اختیاری verbose را نیز به انتهای دستور اضافه نمائید.
بقیه مراحل کار با این فایلهای تولید شده، با نکاتی که تاکنون عنوان شدهاند یکی است. برای مثال اگر میخواهید رشتهی اتصالی پیش فرض را از این Context تولید شده خارج کنید:
public partial class MyDBDataContext : DbContext { protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer(@"Data Source=(local);Initial Catalog=BloggingCore2016;Integrated Security = true"); }
بررسی پارامترهای دیگر ابزار مهندسی معکوس به Code First
اگر دستور dotnet ef dbcontext scaffold --help را صادر کنیم، خروجی راهنمای ذیل را میتوان مشاهده کرد:
Usage: dotnet ef dbcontext scaffold [arguments] [options] Arguments: [connection] The connection string of the database [provider] The provider to use. For example, Microsoft.EntityFrameworkCore.SqlServer Options: -a|--data-annotations Use DataAnnotation attributes to configure the model where possible. If omitted, the output code will use only the fluent API. -c|--context <name> Name of the generated DbContext class. -f|--force Force scaffolding to overwrite existing files. Otherwise, the code will only proceed if no output files would be overwritten. -o|--output-dir <path> Directory of the project where the classes should be output. If omitted, the top-level project directory is used. --schema <schema> Selects a schema for which to generate classes. -t|--table <schema.table> Selects a table for which to generate classes. -e|--environment <environment> The environment to use. If omitted, "Development" is used. -h|--help Show help information -v|--verbose Enable verbose output
- حالت پیش فرض تنظیمات روابط مدلها در این روش، حالت استفاده از Fluent API است. اگر میخواهید آنرا به حالت استفادهی از Data Annotations تغییر دهید، پارامتر a- و یا data-annotations-- را در دستور نهایی ذکر کنید.
- حالت پیش فرض تولید فایلهای نهایی این روش، عدم بازنویسی فایلهای موجود است. اگر میخواهید پس از تغییر بانک اطلاعاتی، مجددا این فایلها را از صفر تولید کنید، پارامتر f- و یا force- را در دستور نهایی ذکر کنید.
بنابراین اگر میخواهید هربار فایلهای نهایی را بازنویسی کنید و همچنین روش کار با Data Annotations را ترجیح میدهید، دستور نهایی، شکل زیر را پیدا خواهد کرد:
dotnet ef dbcontext scaffold "Data Source=(local);Initial Catalog=BloggingCore2016;Integrated Security = true" Microsoft.EntityFrameworkCore.SqlServer -o Entities --context MyDBDataContext --verbose --force --data-annotations
کار با یک بانک اطلاعاتی موجود، با روش مهاجرتهای Code First
فرض کنید میخواهید از یک بانک اطلاعاتی از پیش موجود EF 6.x (یا هر بانک اطلاعاتی از پیش موجود دیگری)، به روش پیش فرض EF Core استفاده کنید. برای این منظور:
- ابتدا جدول migration history قدیمی آنرا حذف کنید؛ چون ساختار آن با EF Core یکی نیست.
- سپس با استفاده از دستور dotnet ef dbcontext scaffold فوق، معادل کلاسها، روابط و Context سازگار با EF Core آنرا تولید کنید.
- در ادامه رشتهی اتصالی پیش فرض آنرا از کلاس Context تولیدی خارج کرده و از یکی از روشهای مطرح شدهی در مطلب «شروع به کار با EF Core 1.0 - قسمت 1 - برپایی تنظیمات اولیه» استفاده کنید.
- سپس نیاز است این Context جدید را توسط متد services.AddDbContext به لیست سرویسهای برنامه اضافه کنید. این مورد نیز در قسمت اول بررسی شدهاست.
- مرحلهی بعد، افزودن جدول __EFMigrationsHistory جدید EF Core، به این بانک اطلاعاتی است. برای این منظور به روش متداول فعال کردن مهاجرتها، دستور ذیل را صادر کنید:
dotnet ef migrations add InitialDatabase
using Microsoft.EntityFrameworkCore.Migrations; namespace Core1RtmEmptyTest.DataLayer.Migrations { public partial class InitialDatabase : Migration { protected override void Up(MigrationBuilder migrationBuilder) { } protected override void Down(MigrationBuilder migrationBuilder) { } } }
سپس دستور به روز رسانی بانک اطلاعاتی را صادر کنید:
dotnet ef database update
پس از این مرحله، روش کار، Code first خواهد بود. برای مثال خاصیتی را به کلاسی اضافه میکنید و سپس دو دستور ذیل را صادر خواهید کرد که در آن v2 یک نام دلخواه است:
dotnet ef migrations add v2 dotnet ef database update
اگر حین کار با NHibernate و SQLite در یک برنامهی دات نت 4 به خطای "Could not create the driver from NHibernate.Driver.SQLite20Driver" برخوردید، راه حل همان مورد فوق است (اضافه کردن useLegacyV2RuntimeActivationPolicy به فایل کانفیگ برنامه).
BloggerToCHM
من برای کار با SQLite از افزونه زیر استفاده میکنم:
https://addons.mozilla.org/en-US/firefox/addon/5817
دیتابیس خودتون را با آن باز کنید.
بعد در برگه execute sql آن، عبارت sql مورد نظر خودتون رو تست کنید تا خطای آن واضح مشخص شود.
همچنین اینجا میتوان بهتر دید که آیا جدول مورد نظر وجود دارد یا خیر.