اشتراک‌ها
SQL Server 2016 و تماس با خانه

How to Turn Off the Phone-Home Option for Standard and Enterprise Edition
Enterprise customers may construct Group Policy to opt in or out of telemetry collection by setting a registry-based policy. The relevant registry key and settings are as follows:
Key = HKEY_CURRENT_USER\Software\Microsoft\Microsoft SQL Server\130
RegEntry name = CustomerFeedback
Entry type DWORD: 0 is opt out, 1 is opt in 

SQL Server 2016 و تماس با خانه
نظرات مطالب
ارتقاء به ASP.NET Core 1.0 - قسمت 5 - فعال سازی صفحات مخصوص توسعه دهنده‌ها
در متد public void Configure کلاس آغازین برنامه، امکان تزریق وابستگی‌های تنظیمات برنامه وجود دارد:
public class Startup
{
    private readonly IConfiguration _config;

    public Startup(IConfiguration config)
    {
        _config = config;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        var value = _config["key"];
    }

    public void Configure(IApplicationBuilder app, IConfiguration config)
    {
        var value = config["key"];
    }
}
نظرات مطالب
EF Code First #3
باتشکر.من وقتی از متادیتای خواص  [ForeignKey("FK_User_Id")] استفاده می‌کنم چنین خطایی رو سیستم صادر می‌کنه:
Additional information: The ForeignKeyAttribute on property 'User' on type 'Models.Project' is not valid. The foreign key name 'FK_User_Id' was not found on the dependent type 'Models.Project'. The Name value should be a comma separated list of foreign key property names
تمامی موارد رو هم بر طبق مثال رعایت کردم

نظرات مطالب
EF Code First #3
سلام؛  موقع استفاده از annotation‌ها
public class KalaType
{
    [Key, Column(Order = 0)]
    public int kalaID { get; set; }
    [Key, Column(Order = 1)]
    public int typeID { get; set; }
...
}
با اینکه از
using System.Data.Entity;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.Design;
using System.ComponentModel.DataAnnotations.Resources;
استفاده میکنم،این ارور میده! چیکار کنم؟
Compiler Error Message: CS0246: The type or namespace name 'Column' could not be found (are you missing a using directive or an assembly reference?)
نظرات مطالب
چند نکته کاربردی درباره Entity Framework
سلام . من یه راهنمایی میخوام ممنون میشم کمکم کنین برا آپدیت مشکل دارم،کدش رو به این صورت نوشتم اما چنین اروری میده(An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key. )

public void InsertOrUpdate(Core.Models.PersonelAction personelAction {
            if (personelAction.Id == default(int))
            {
                _unitOfWork.Entry(personelAction).State = EntityState.Added;
            }
            else
            {
                 _unitOfWork.Entry(personelAction).State=EntityState.Modified;

            }
        }
مطالب
پیاده سازی یک تامین کننده MySQL برای ASP.NET Identity
در این مقاله جایگزینی پیاده سازی پیش فرض ASP.NET Identity را بررسی می‌کنیم. در ادامه خواهید خواند:

  • جزئیات نحوه پیاده سازی یک Storage Provider برای ASP.NET Identity
  • تشریح اینترفیس هایی که باید پیاده سازی شوند، و نحوه استفاده از آنها در ASP.NET Identity
  • ایجاد یک دیتابیس MySQL روی Windows Azure
  • نحوه استفاده از یک ابزار کلاینت (MySQL Workbench) برای مدیریت دیتابیس مذکور
  • نحوه جایگزینی پیاده سازی سفارشی با نسخه پیش فرض در یک اپلیکیشن ASP.NET MVC
در انتهای این مقاله یک اپلیکیشن ASP.NET MVC خواهیم داشت که از ASP.NET Identity و تامین کننده سفارشی جدید استفاده می‌کند. دیتابیس اپلیکیشن MySQL خواهد بود و روی Windows Azure میزبانی می‌شود. سورس کد کامل این مثال را هم می‌توانید از این لینک دریافت کنید.


پیاده سازی یک Storage Provider سفارشی برای ASP.NET Identity

ASP.NET Identity سیستم توسعه پذیری است که می‌توانید بخش‌های مختلف آن را جایگزین کنید.در این سیستم بناهای سطح بالایی مانند Managers و Stores وجود دارند.
Managers کلاس‌های سطح بالایی هستند که توسعه دهندگان از آنها برای اجرای عملیات مختلف روی ASP.NET Identity استفاده می‌کنند. مدیریت کننده‌های موجود عبارتند از UserManager و RoleManager. کلاس UserManager برای اجرای عملیات مختلف روی کاربران استفاده می‌شود، مثلا ایجاد کاربر جدید یا حذف آنها. کلاس RoleManager هم برای اجرای عملیات مختلف روی نقش‌ها استفاده می‌شود.

Stores کلاس‌های سطح پایین‌تری هستند که جزئیات پیاده سازی را در بر می‌گیرند، مثلا اینکه موجودیت‌های کاربران و نقش‌ها چگونه باید ذخیره و بازیابی شوند. این کلاس‌ها با مکانیزم ذخیره و بازیابی تلفیق شده اند. مثلا Microsoft.AspNet.Identity.EntityFramework کلاسی با نام UserStore دارد که برای ذخیره و بازیابی User‌ها و داده‌های مربوطه توسط EntityFramework استفاده می‌شود.

Managers از Stores تفکیک شده اند و هیچ وابستگی ای به یکدیگر ندارند. این تفکیک بدین منظور انجام شده که بتوانید مکانیزم ذخیره و بازیابی را جایگزین کنید، بدون اینکه اپلیکیشن شما از کار بیافتد یا نیاز به توسعه بیشتر داشته باشد. کلاس‌های Manager می‌توانند با هر Store ای ارتباط برقرار کنند. از آنجا که شما از API‌های سطح بالای UserManager برای انجام عملیات CRUD روی کاربران استفاده می‌کنید، اگر UserStore را با پیاده سازی دیگری جایگزین کنید، مثلا AzureTable Storage یا MySql، نیازی به بازنویسی اپلیکیشن نیست.

در مثال جاری پیاده سازی پیش فرض Entity Framework را با یک  تامین کننده MySQL جایگزین می‌کنیم.

پیاده سازی کلاس‌های Storage
برای پیاده سازی تامین کننده‌های سفارشی، باید کلاس هایی را پیاده سازی کنید که همتای آنها در Microsoft.AspNet.Identity.EntityFramework وجود دارند:
  • <UserStore<TUser
  • IdentityUser
  • <RoleStore<TRole
  • IdentityRole
پیاده سازی پیش فرض Entity Framework را در تصاویر زیر مشاهده می‌کنید.
Users

Roles

در مخزن پیش فرض ASP.NET Identity EntityFramework کلاس‌های بیشتری برای موجودیت‌ها مشاهده می‌کنید.

  • IdentityUserClaim
  • IdentityUserLogin
  • IdentityUserRole
همانطور که از نام این کلاس‌ها مشخص است، اختیارات، نقش‌ها و اطلاعات ورود کاربران توسط این کلاس‌ها معرفی می‌شوند. در مثال جاری این کلاس‌ها را پیاده سازی نخواهیم کرد، چرا که بارگذاری اینگونه رکوردها از دیتابیس به حافظه برای انجام عملیات پایه (مانند افزودن و حذف اختیارات کاربران) سنگین است. در عوض کلاس‌های backend store اینگونه عملیات را بصورت مستقیم روی دیتابیس اجرا خواهند کرد. بعنوان نمونه متد ()UserStore.GetClaimsAsync را در نظر بگیرید. این متد به نوبه خود متد (userClaimTable.FindByUserId(user.Id را فراخوانی می‌کند که یک کوئری روی جدول مربوطه اجرا می‌کند و لیستی از اختیارات کاربر را بر می‌گرداند.
public Task<IList<Claim>> GetClaimsAsync(IdentityUser user)
{
    ClaimsIdentity identity = userClaimsTable.FindByUserId(user.Id);
    return Task.FromResult<IList<Claim>>(identity.Claims.ToList());
}
برای پیاده سازی یک تامین کننده سفارشی MySQL مراحل زیر را دنبال کنید.
1. کلاس کاربر را ایجاد کنید، که اینترفیس IUser را پیاده سازی می‌کند.
public class IdentityUser : IUser
{
    public IdentityUser(){...}

    public IdentityUser(string userName) (){...}

    public string Id { get; set; }

    public string UserName { get; set; }

    public string PasswordHash { get; set; }

    public string SecurityStamp { get; set; }
}
2. کلاس User Store را ایجاد کنید، که اینترفیس‌های IUserStore, IUserClaimStore, IUserLoginStore, IUserRoleStore و IUserPasswordStore را پیاده سازی می‌کند. توجه کنید که تنها اینترفیس IUserStore را باید پیاده سازی کنید، مگر آنکه بخواهید از امکاناتی که دیگر اینترفیس‌ها ارائه می‌کنند هم استفاده کنید.
public class UserStore : IUserStore<IdentityUser>,
                         IUserClaimStore<IdentityUser>,
                         IUserLoginStore<IdentityUser>,
                         IUserRoleStore<IdentityUser>,
                         IUserPasswordStore<IdentityUser>
{
    public UserStore(){...}

    public Task CreateAsync(IdentityUser user){...}

    public Task<IdentityUser> FindByIdAsync(string userId){...}   
...
}
3. کلاس Role را ایجاد کنید که اینترفیس IRole را پیاده سازی می‌کند.
public class IdentityRole : IRole
{
    public IdentityRole(){...}

    public IdentityRole(string roleName) (){...}

    public string Id { get; set; }

    public string Name { get; set; }
}
4. کلاس Role Store را ایجاد کنید که اینترفیس IRoleStore را پیاده سازی می‌کند. توجه داشته باشید که پیاده سازی این مخزن اختیاری است و در صورتی لازم است که بخواهید از نقش‌ها در سیستم خود استفاده کنید.
public class RoleStore : IRoleStore<IdentityRole>                        
{
    public RoleStore(){...}

    public Task CreateAsync(IdentityRole role){...}

    public Task<IdentityRole> FindByIdAsync(string roleId){...}   
....
}
کلاس‌های بیشتری هم وجود دارند که مختص پیاده سازی مثال جاری هستند.
  • MySQLDatabase: این کلاس اتصال دیتابیس MySql و کوئری‌ها را کپسوله می‌کند. کلاس‌های UserStore و RoleStore توسط نمونه ای از این کلاس وهله سازی می‌شوند.
  • RoleTable: این کلاس جدول Roles و عملیات CRUD مربوط به آن را کپسوله می‌کند.
  • UserClaimsTable: این کلاس جدول UserClaims و عملیات CRUD مربوط به آن را کپسوله می‌کند.
  • UserLoginsTable: این کلاس جدول UserLogins و عملیات CRUD مربوط به آن را کپسوله می‌کند.
  • UserRolesTable: این کلاس جدول UserRoles و عملیات CRUD مربوطه به آن را کپسوله می‌کند.
  • UserTable: این کلاس جدول Users و عملیات CRUD مربوط به آن را کپسوله می‌کند.

ایجاد یک دیتابیس MySQL روی Windows Azure

1. به پورتال مدیریتی Windows Azure وارد شوید.
2. در پایین صفحه روی NEW+ کلیک کنید و گزینه STORE را انتخاب نمایید.

در ویزارد Choose Add-on به سمت پایین اسکرول کنید و گزینه ClearDB MySQL Database را انتخاب کنید. سپس به مرحله بعد بروید.

4. راهکار Free بصورت پیش فرض انتخاب شده، همین گزینه را انتخاب کنید و نام دیتابیس را به IdentityMySQLDatabase تغییر دهید. نزدیک‌ترین ناحیه (region) به خود را انتخاب کنید و به مرحله بعد بروید.

5. روی علامت checkmark کلیک کنید تا دیتابیس شما ایجاد شود. پس از آنکه دیتابیس شما ساخته شد می‌توانید از قسمت ADD-ONS آن را مدیریت کنید.

6. همانطور که در تصویر بالا می‌بینید، می‌توانید اطلاعات اتصال دیتابیس (connection info) را از پایین صفحه دریافت کنید.

7. اطلاعات اتصال را با کلیک کردن روی دکمه مجاور کپی کنید تا بعدا در اپلیکیشن MVC خود از آن استفاده کنیم.


ایجاد جداول ASP.NET Identity در یک دیتابیس MySQL

ابتدا ابزار MySQL Workbench را نصب کنید.
1. ابزار مذکور را از اینجا دانلود کنید.
2. هنگام نصب، گزینه Setup Type: Custom را انتخاب کنید.
3. در قسمت انتخاب قابلیت ها، گزینه‌های Applications و MySQLWorkbench را انتخاب کنید و مراحل نصب را به اتمام برسانید.
4. اپلیکیشن را اجرا کرده و روی MySQLConnection کلیک کنید تا رشته اتصال جدیدی تعریف کنید. رشته اتصالی که در مراحل قبل از Azure MySQL Database کپی کردید را اینجا استفاده کنید. بعنوان مثال:
 Connection Name: AzureDB; Host Name: us-cdbr-azure-west-b.cleardb.com; Username: <username>; Password: <password>; Default Schema: IdentityMySQLDatabase 
5. پس از برقراری ارتباط با دیتابیس، یک برگ Query جدید باز کنید. فرامین زیر را برای ایجاد جداول مورد نیاز کپی کنید.
CREATE TABLE `IdentityMySQLDatabase`.`users` (
  `Id` VARCHAR(45) NOT NULL,
  `UserName` VARCHAR(45) NULL,
  `PasswordHash` VARCHAR(100) NULL,
  `SecurityStamp` VARCHAR(45) NULL,
  PRIMARY KEY (`id`));

CREATE TABLE `IdentityMySQLDatabase`.`roles` (
  `Id` VARCHAR(45) NOT NULL,
  `Name` VARCHAR(45) NULL,
  PRIMARY KEY (`Id`));

CREATE TABLE `IdentityMySQLDatabase`.`userclaims` (
  `Id` INT NOT NULL AUTO_INCREMENT,
  `UserId` VARCHAR(45) NULL,
  `ClaimType` VARCHAR(100) NULL,
  `ClaimValue` VARCHAR(100) NULL,
  PRIMARY KEY (`Id`),
  FOREIGN KEY (`UserId`)
    REFERENCES `IdentityMySQLDatabase`.`users` (`Id`) on delete cascade);

CREATE TABLE `IdentityMySQLDatabase`.`userlogins` (
  `UserId` VARCHAR(45) NOT NULL,
  `ProviderKey` VARCHAR(100) NULL,
  `LoginProvider` VARCHAR(100) NULL,
  FOREIGN KEY (`UserId`)
    REFERENCES `IdentityMySQLDatabase`.`users` (`Id`) on delete cascade);

CREATE TABLE `IdentityMySQLDatabase`.`userroles` (
  `UserId` VARCHAR(45) NOT NULL,
  `RoleId` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`UserId`, `RoleId`),
  FOREIGN KEY (`UserId`)
    REFERENCES `IdentityMySQLDatabase`.`users` (`Id`) 
on delete cascade
on update cascade,
  FOREIGN KEY (`RoleId`)
    REFERENCES `IdentityMySQLDatabase`.`roles` (`Id`)
on delete cascade
on update cascade);
6. حالا تمام جداول لازم برای ASP.NET Identity را در اختیار دارید، دیتابیس ما MySQL است و روی Windows Azure میزبانی شده.


ایجاد یک اپلیکیشن ASP.NET MVC و پیکربندی آن برای استفاده از MySQL Provider

2. در گوشه سمت راست پایین صفحه روی دکمه Download Zip کلیک کنید تا کل پروژه را دریافت کنید.
3. محتوای فایل دریافتی را در یک پوشه محلی استخراج کنید.
4. پروژه AspNet.Identity.MySQL را باز کرده و آن را کامپایل (build) کنید.
5. روی نام پروژه کلیک راست کنید و گزینه Add, New Project را انتخاب نمایید. پروژه جدیدی از نوع ASP.NET Web Application بسازید و نام آن را به IdentityMySQLDemo تغییر دهید.

6. در پنجره New ASP.NET Project قالب MVC را انتخاب کنید و تنظیمات پیش فرض را بپذیرید.

7. در پنجره Solution Explorer روی پروژه IdentityMySQLDemo کلیک راست کرده و Manage NuGet Packages را انتخاب کنید. در قسمت جستجوی دیالوگ باز شده عبارت "Identity.EntityFramework" را وارد کنید. در لیست نتایج این پکیج را انتخاب کرده و آن را حذف (Uninstall) کنید. پیغامی مبنی بر حذف وابستگی‌ها باید دریافت کنید که مربوط به پکیج EntityFramework است، گزینه Yes را انتخاب کنید. از آنجا که کاری با پیاده سازی فرض نخواهیم داشت، این پکیج‌ها را حذف می‌کنیم.

8. روی پروژه IdentityMySQLDemo کلیک راست کرده و Add, Reference, Solution, Projects را انتخاب کنید. در دیالوگ باز شده پروژه AspNet.Identity.MySQL را انتخاب کرده و OK کنید.

9. در پروژه IdentityMySQLDemo پوشه Models را پیدا کرده و کلاس IdentityModels.cs را حذف کنید.

10. در پروژه IdentityMySQLDemo تمام ارجاعات ";using Microsoft.AspNet.Identity.EntityFramework" را با ";using AspNet.Identity.MySQL" جایگزین کنید.

11. در پروژه IdentityMySQLDemo تمام ارجاعات به کلاس "ApplicationUser" را با "IdentityUser" جایگزین کنید.

12. کنترلر Account را باز کنید و متد سازنده آنرا مطابق لیست زیر تغییر دهید.

public AccountController() : this(new UserManager<IdentityUser>(new UserStore(new MySQLDatabase())))
{

}

13. فایل web.config را باز کنید و رشته اتصال DefaultConnection را مطابق لیست زیر تغییر دهید.

<add name="DefaultConnection" connectionString="Database=IdentityMySQLDatabase;Data Source=<DataSource>;User Id=<UserID>;Password=<Password>" providerName="MySql.Data.MySqlClient" />

مقادیر <DataSource>, <UserId> و <Password> را با اطلاعات دیتابیس خود جایگزین کنید.


اجرای اپلیکیشن و اتصال به دیتابیس MySQL

1. روی پروژه IdentityMySQLDemo کلیک راست کرده و Set as Startup Project را انتخاب کنید.
2. اپلیکیشن را با Ctrl + F5 کامپایل و اجرا کنید.
3. در بالای صفحه روی Register کلیک کنید.
4. حساب کاربری جدیدی بسازید.

5. در این مرحله کاربر جدید باید ایجاد شده و وارد سایت شود.

6. به ابزار MySQL Workbench بروید و محتوای جداول IdentityMySQLDatabase را بررسی کنید. جدول users را باز کنید و اطلاعات کاربر جدید را بررسی نمایید.

برای ساده نگاه داشتن این مقاله از بررسی تمام کدهای لازم خودداری شده، اما اگر مراحل را دنبال کنید و سورس کد نمونه را دریافت و بررسی کنید خواهید دید که پیاده سازی تامین کنندگان سفارشی برای ASP.NET Identity کار نسبتا ساده ای است.

مطالب
C# 8.0 - Ranges & Indices
نوع Span به همراه NET Core 2.1. ارائه شد. یکی از مهم‌ترین مزایای آن امکان دسترسی به قسمتی از حافظه (توسط متد Split آن)، بدون ایجاد سربار کپی یا تخصیص مجدد حافظه‌ای برای دسترسی به آن است. قدم بعدی، بسط این قابلیت به امکانات ذاتی زبان #C است؛ تحت عنوان ویژگی Ranges که امکان دسترسی مستقیم به بازه‌ای/قسمتی از آرایه‌ها، رشته‌ها و یا Spanها را میسر می‌کند.


معرفی عملگر Hat

برای دسترسی به آخرین عضو یک آرایه عموما از روش زیر استفاده می‌شود:
var integerArray = new int[3];
var lastItem = integerArray[integerArray.Length - 1];
یعنی از آخر شروع به شمارش کرده و 1 واحد از آن کم می‌کنیم (این عدد 1 را به‌خاطر داشته باشید) و یا اگر بخواهیم از LINQ استفاده کنیم می‌توان از متد Last آن استفاده کرد:
var integerList = integerArray.ToList();
integerList.Last();
همچنین اگر بخواهیم دومین عنصر از آخر آن‌را دریافت کنیم:
var secondToLast = integerArray[integerArray.Length - 2];
نیز مجددا از آخر شروع به شمارش کرده و 2 واحد، از آن کم می‌کنیم (این عدد 2 را نیز به‌خاطر داشته باشید).

این شمردن‌های از آخر در C# 8.0 توسط ارائه‌ی عملگر hat یا همان ^ که پیشتر کار xor را انجام می‌داد (و البته هنوز هم در جای خودش همین مفهوم را دارد)، میسر شده‌است:
var lastItem = integerArray[^1];
این قطعه کد یعنی به دنبال ایندکس X، از آخر آرایه هستیم.

نکته‌ی مهم: کسانیکه شروع به آموزش برنامه نویسی می‌کنند، مدتی طول می‌کشد تا عادت کنند که اولین ایندکس یک آرایه از صفر شروع می‌شود. در اینجا باید درنظر داشت که با بکارگیری «عملگر کلاه»، آخرین ایندکس یک آرایه از «یک» شروع می‌شود و نه از صفر. برای نمونه در مثال زیر به خوبی تفاوت بین ایندکس از ابتدا و ایندکس از انتها را می‌توانید مشاهده کنید:
var words = new string[]
{
                // index from start    index from end
    "The",      // 0                   ^9
    "quick",    // 1                   ^8
    "brown",    // 2                   ^7
    "fox",      // 3                   ^6
    "jumped",   // 4                   ^5
    "over",     // 5                   ^4
    "the",      // 6                   ^3
    "lazy",     // 7                   ^2
    "dog"       // 8                   ^1
};              // 9 (or words.Length) ^0
آرایه‌ی فوق، 9 عضو دارد. در این حالت اولین عنصر آن با ایندکس صفر قابل دسترسی است. در همین حالت همین ایندکس را اگر از آخر محاسبه کنیم، 9 خواهد بود و همینطور برای مابقی.
در حالت کلی ایندکس n^ معادل sequence.Length - n است. بنابراین sequence[^0] به معنای sequence[sequence.Length] است و هر دو مورد یک index out of range exception را صادر می‌کنند.

IDE نیز با فعال سازی C# 8.0، زمانیکه به قطعه کد زیر می‌رسد، زیر words.Length - 1 خط کشیده و پیشنهاد می‌دهد که بهتر است از 1^ استفاده کنید:
Console.WriteLine($"The last word is {words[words.Length - 1]}");



معرفی نوع جدید Index

در C# 8.0 زمانیکه می‌نویسم 1^، در حقیقت قطعه کد زیر را ایجاد کرده‌ایم:
var index = new Index(value: 1, fromEnd: true);
Index indexStruct = ^1;
var indexShortHand = ^1;
Index یک struct و نوع جدید در C# 8.0 می‌باشد که در فضای نام System قرار گرفته‌است. سه سطر فوق دقیقا به یک معنا هستند و هر کدام خلاصه شده و ساده شده‌ی سطر قبلی است.
در سطر اول، پارامتر fromEnd نیز قابل تعریف است. این fromEnd با مقدار true، همان عملگر ^ در اینجا است و عدم ذکر این عملگر به معنای false بودن آن است:
int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Console.WriteLine(a[a.Length – 2]); // will write 8 on console.
Console.WriteLine(a[^2]); // will write 8 on console.

Index i5 = 5;
Console.WriteLine(a[i5]);        //will write 5 on console.

Index i2fromEnd = ^2;
Console.WriteLine(a[i2fromEnd]); // will write 8 on console.
در این مثال دو نمونه کاربرد fromEnd با مقدار false و سپس true را ملاحظه می‌کنید. در حالتیکه Index i5 = 5 تعریف شده‌است، دسترسی به عناصر آرایه همانند قبل از ایندکس صفر و از آغاز شروع می‌شود و نه از ایندکس یک.


روش دسترسی به بازه‌ای از اعضای یک آرایه تا پیش از C# 8.0

فرض کنید آرایه‌ای از اعداد بین 1 تا 10 را به صورت زیر ایجاد کرده‌اید:
var numbers = Enumerable.Range(1, 10).ToArray();
اکنون اگر بخواهیم به بازه‌ی مشخصی درون این آرایه دسترسی پیدا کنیم، می‌توان حداقل به یکی از دو روش زیر عمل کرد:
var (start, end) = (1, 7); 
var length = end - start; 

// Using LINQ 
var subset1 = numbers.Skip(start).Take(length);
 
// Or using Array.Copy 
var subset2 = new int[length];
Array.Copy(numbers, start, subset2, 0, length);
یا می‌توان برای مثال توسط LINQ، از متدهای Skip و Take آن برای جدا کردن بازه‌ای از آرایه‌ی numbers استفاده کرد و یا حتی می‌توان از روش کپی کردن آرایه‌ها به آرایه‌ای جدید نیز کمک گرفت که در هر دو حالت، مراحلی که باید طی شوند قابل توجه است. با ارائه‌ی C# 8.0، این نوع دسترسی‌ها جزئی از قابلیت‌های زبان شده‌اند.


روش دسترسی به بازه‌ای از اعضای یک آرایه در C# 8.0

در C# 8.0 برای دسترسی به بازه‌ای از عناصر یک آرایه می‌توان از range expression که به صورت x..y نوشته می‌شود، استفاده کرد. در ادامه، مثال‌هایی را از کاربردهای عبارت .. ملاحظه می‌کنید:
var myArray = new string[] { "Item1", "Item2", "Item3", "Item4", "Item5" };
3..1 به معنای انتخاب بازه‌ای از المان 2 تا المان 3 است. در اینجا به واژه‌ی «المان» دقت کنید که معادل ایندکس آن در آرایه نیست. یعنی عدد ابتدای یک بازه دقیقا به ایندکس آن در آرایه اشاره می‌کند و عدد انتهای بازه، به ایندکس ماقبل آن (از این جهت که بتوان توسط 0^، انتهای بازه را مشخص کرد؛ بدون دریافت استثنای index out of range). به همین جهت به ابتدای بازه می‌گویند inclusive و به انتهای آن exclusive:
 var fromIndexToX = myArray[1..3]; // = [Item2, Item3]
1^..1 به معنای انتخاب بازه‌ای از المان 2، تا المان یکی مانده به آخر است:
var fromIndexToXFromTheEnd = myArray[1..^1]; // = [ "Item2", "Item3", "Item4" ]

ذکر انتهای بازه اجباری نیست و اگر ذکر نشود به معنای 0^ است. برای مثال ..1 به معنای انتخاب بازه‌ای از المان 2، تا آخرین المان است:
var fromAnIndexToTheEnd = myArray[1..]; // = [ "Item2", "Item3", "Item4", "Item5" ]

ذکر ابتدای بازه نیز اجباری نیست و اگر ذکر نشود به معنای عدد صفر است. برای مثال 3.. به معنای انتخاب بازه‌ای از اولین المان، تا سومین المان است:
 var fromTheStartToAnIndex = myArray[..3]; // = [ "Item1", "Item2", "Item3" ]

اگر ابتدا و انتهای بازه ذکر نشوند، کل بازه و تمام عناصر آن بازگشت داده می‌شوند:
 var entireRange = myArray[..]; // = [ "Item1", "Item2", "Item3", "Item4", "Item5" ]
همچنین [0^..0] نیز به معنای کل بازه است.

مثالی دیگر: بازنویسی یک حلقه‌ی for با foreach
حلقه‌ی for زیر را
var myArray = new string[] { "Item1", "Item2", "Item3", "Item4", "Item5" };
for (int i = 1; i <= 3; i++)
{
  Console.WriteLine(myArray[i]);
}
توسط range expression می‌توان به صورت زیر بازنویسی کرد:
foreach (var item in myArray[1..4]) // = [ "Item2", "Item3", "Item4" ]
{
  Console.WriteLine(item);
}
بنابراین همانطور که مشاهده می‌کنید، ذکر بازه‌ی 4..1 به صورت حلقه‌ی for (int i = 1; i < 4; i++) تفسیر می‌شود و نه حلقه‌ی for (int i = 1; i <= 4; i++)
یعنی ابتدای آن inclusive است و انتهای آن exclusive


چند مثال کاربردی و متداول از بازه‌ها

using System;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        private static readonly int[] _numbers = Enumerable.Range(1, 10).ToArray();

        static void Main()
        {
            var skip2CharactersAndTake2Characters = _numbers[2..4]; // صرفنظر کردن از دو عنصر اول و سپس انتخاب دو عنصر
            var skipFirstAndLastCharacter = _numbers[1..^1]; // صرفنظر کردن از دو عنصر اول و آخر
            var last3Characters = _numbers[^3..]; // انتخاب بازه‌ای شامل سه عنصر آخر
            var first4Characters = _numbers[0..4]; // دریافت بازه‌ای از 4 عنصر اول
            var rangeStartFrom2 = _numbers[2..]; // دریافت بازه‌ای شروع شده از المان دوم تا آخر
            var skipLast3Characters = _numbers[..^3]; // صرفنظر کردن از سه المان آخر
            var rangeAll = _numbers[..]; // انتخاب کل بازه
        }
    }
}


معرفی نوع جدید Range

در C# 8.0 زمانیکه می‌نویسم 4..1، در حقیقت قطعه کد زیر را ایجاد کرده‌ایم:
var range = new Range(1, 4);
Range rangeStruct = 1..4;
var rangeShortHand = 1..4;
Range نیز یک struct و نوع جدید در C# 8.0 می‌باشد که در فضای نام System قرار گرفته‌است. سه سطر فوق دقیقا به یک معنا هستند و هر کدام خلاصه شده و ساده شده‌ی سطر قبلی است.

یک مثال: استفاده از نوع جدید Range به عنوان پارامتر یک متد
using System;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        private static readonly int[] _numbers = Enumerable.Range(1, 10).ToArray();
        static void Print(Range range) => Console.WriteLine($"{range} => {string.Join(", ", _numbers[range])}");

        static void Main()
        {
            Print(1..3); // 1..3 => 2, 3
            Print(..3);      // 0..3 => 1, 2, 3
            Print(3..);      // 3..^0 => 4, 5, 6, 7, 8, 9, 10
            Print(1..^1);    // 1..^1 => 2, 3, 4, 5, 6, 7, 8, 9
            Print(^2..^1);   // ^2..^1 => 9
        }
    }
}
همانطور که ملاحظه می‌کنید، Range را می‌توان به عنوان پارامتر متدها نیز استفاده و بر روی آرایه‌ها اعمال کرد؛ اما با <List<T سازگار نیست.

مثالی دیگر: استفاده از Range به عنوان جایگزینی برای متد String.Substring

از Range می‌توان برای کار بر روی رشته‌ها و انتخاب قسمتی از آن‌ها نیز استفاده کرد:
Console.WriteLine("123456789"[1..4]); // Would output 234
چند مثال دیگر:
var helloWorldStr = "Hello, World!";

var hello = helloWorldStr[..5];
Console.WriteLine(hello); // Output: Hello

var world = helloWorldStr[7..];
Console.WriteLine(world); // Output: World!

var world2 = helloWorldStr[^6..]; // Take the last 6 characters
Console.WriteLine(world); // Output: World!


سؤال: زمانیکه بازه‌ای از یک آرایه را انتخاب می‌کنیم، آیا یک آرایه‌ی جدید ایجاد می‌شود، یا هنوز به همان آرایه‌ی قبلی اشاره می‌کند؟

پاسخ: یک آرایه‌ی جدید ایجاد می‌شود؛ اما می‌توان با فراخوانی متد ()array.AsSpan پیش از انتخاب یک بازه، بازه‌ای را تولید کرد که دقیقا به همان آرایه‌ی اصلی اشاره می‌کند و یک کپی جدید نیست:
var arr = (new[] { 1, 4, 8, 11, 19, 31 }).AsSpan();
var range = arr[2..5];

ref int elt1 = ref range[1];
elt1 = -1;

int copiedElement = range[2];
copiedElement = -2;

Console.WriteLine($"range[1]: {range[1]}, range[2]: {range[2]}"); // output: range[1]: -1, range[2]: 19
Console.WriteLine($"arr[3]: {arr[3]}, arr[4]: {arr[4]}"); // output: arr[3]: -1, arr[4]: 19
در این مثال، آرایه‌ی اصلی را ابتدا تبدیل به یک Span کرده‌ایم و سپس بازه‌ای از روی آن انتخاب شده‌است. به همین جهت است که زمانیکه از ref locals برای تغییر عضوی از این بازه استفاده می‌شود، این تغییر بر روی آرایه‌ی اصلی نیز تاثیر می‌گذارد.
نظرات مطالب
روشی برای DeSerialize کردن QueryString به یک کلاس
جهت افزودن پشتیبانی از حالت POST کد متد را به شکل زیر تغییر دهید:
 public T GetFromQueryString<T>(RequestType type=RequestType.GET) where T : new()
        {
            var obj = new T();
            var properties = typeof(T).GetProperties();

            var queries =new NameValueCollection();
            if(type==RequestType.GET)
                queries= HttpContext.Current.Request.QueryString;
            else
            {
                queries = HttpContext.Current.Request.Form;
            }

            foreach (var property in properties)
            {
                foreach (Attribute attribute in property.GetCustomAttributes(true))
                {
                    var requestBodyField = attribute as RequestBodyField; 
                    if (requestBodyField == null) continue;

                    //get value of query string
                    var valueAsString = queries[requestBodyField.Field];

                    if (valueAsString == null)
                    {
                        var keys = from key in queries.AllKeys where key.StartsWith(requestBodyField.Field) select key;

                        if(!keys.Any())
                            continue;

                        var collection = new NameValueCollection();

                        foreach (var key in keys)
                        {
                            var openBraketIndex = key.IndexOf("[", StringComparison.Ordinal);
                            var closeBraketIndex = key.IndexOf("]", StringComparison.Ordinal);

                            if (openBraketIndex < 0 || closeBraketIndex < 0)
                                throw new Exception("query string is crupted.");

                            openBraketIndex++;
                            //get key in [...]
                            var fieldName = key.Substring(openBraketIndex, closeBraketIndex - openBraketIndex);
                            collection.Add(fieldName, queries[key]);
                        }
                        property.SetValue(obj, collection, null);
                        continue;
                    }

                    var converter = TypeDescriptor.GetConverter(property.PropertyType);
                    var value = converter.ConvertFrom(valueAsString);

                    if (value == null)
                        continue;

                    property.SetValue(obj, value, null);
                }
            }
            return obj;
        }
مطالب
Embed کردن SQL Server Express 2008 در یک برنامه
مقدمه
نصب Microsoft Sql Server یکی از عملیات مشکل برای کاربر نهایی می‌باشد. برای رفع این مشکل، باید آنرا بصورت اتوماتیک و بدون درگیر کردن کاربر آن را نصب کنیم.برای اینکار دو روش موجود است:
1) استفاده از فایل Configure.ini
2) ارسال پارامتر به فایل Setup.exe از طریق Command Prompt

قابلیت‌های نسخه‌های مختلف Sql Server Express 2008
 نسخه / قابلیت Database Engine Management Studio Basic Full-Text Search Reporting Services
Management Studio Basic    X    
 Runtime Only
 X      
 with Tools   X  X    
  with Advanced Services     X  X  X  X

(SQL Server 2008 Management Studio Express (SSMSE
ابزارهای مدیریتی گرافیکی رایگان برای پیکربندی، مدیریت و اداره کردن برنامه‌های SQL Server Express 2008
استفاده برای مدیریت چندین نمونه از موتور پایگاه داده SQL Server که توسط نسخه‌های مختلف SQL Server 2008 ساخته شده اند.

(SQL Server 2008 Express (Runtime Only
موتور پایگاه داده SQL Server برای ساخت، ذخیره سازی، بروز رسانی و واکشی داده

SQL Server 2008 Express with Tools
موتور پایگاه داده SQL Server برای ساخت، ذخیره سازی، بروز رسانی و واکشی داده
SQL Server Management Studio Basic - یک ابزار مدیریتی ویژوال برای ساخت، ویرایش و مدیریت پایگاه‌های داده

SQL Server 2008 Express with Advanced Services
موتور پایگاه داده SQL Server برای ساخت، ذخیره سازی، بروز رسانی و واکشی داده
SQL Server Management Studio Basic - یک ابزار مدیریتی ویژوال برای ساخت، ویرایش و مدیریت پایگاه‌های داده
Full-Text Search - یک موتور قدرتمند و پرسرعت برای جستجوی داده‌های متن-فشرده

دو حالت برای نصب SQL Server وجود دارد:
نصب یک نمونه جدید
آپگرید

نصب SQL Server Express 2008 از طریق Command Prompt
1) پس از دانلود SQL Server Express 2008 با پارامتر X/ انرا از حالت فشرده خارج کنید.
برای این کار Command Prompt (یا همان cmd) را باز کنید و با دستور cd به مسیری که فایل  SQL Server Express هست بروید.
حالا نام فایل نصب را همراه با پارامتر X/ در cmd تایپ کنید. مثلا: SQLExpr32_x86_enu.exe /x
نکته: اگر فایل یا سی دی نصب ویژوال استودیو 2010 را دارید می‌توانید فایل نصب SQL Server Express را در مسیر WCU\SSE\ پیدا کنید.
2) همانطور که می‌بینید یک مسیر برای Extract از شما خواسته شده. یک مسیر وراد کنید.
3) در مسیر ساخته شده، یک فایل با پسوند bat. بسازید و آنرا یا یک ویرایشگر متنی باز کنید و دستورات زیر را در آن تایپ کنید:
Setup.exe /q /Action=Install /Hideconsole /Features=SQL,Tools
/InstanceName=SQLExpress /SQLSYSADMINACCOUNTS="Builtin\Administrators"
/SQLSVCACCOUNT="<DomainName\UserName>" /SQLSVCPASSWORD="<StrongPassword>

توضیح پارامترهای فوق بشرح زیر است:
q/ (اختیاری): اینکه Setup به حالت خاموش (quiet mode) و بدون رابط کاربری اجرا شود.
Action/ (الزامی): عملیاتی که باید انجام شود. این پارامتر مقدار install و upgrade را قبول می‌کند.
Features/ (الزامی): اینکه کدام قابلیت‌های SQL Server باید نصب شوند.
HideConsole/ (اختیاری): اگر از این پارامتر استفاده شود، پنجره کنسول نمایش داده نخواهد شد.
InstanceName/ (الزامی): نام نمونه ایی که باید نصب شود.
SQLSYSADMINACCOUNTS/ (الزامی): مقررات لوگین برای اعضای با نقش "مدیر سیستم".
SQLSVCACCOUNT/ (الزامی): تعیین اکانتی که سرویس SQL Server را در Startup ویندوز اجرا کند.
SQLSVCACCOUNT/ (اگر از یک اکانت لوکال یا تحت Domain استفاده کنید الزامی است): تعیین پسورد اکانت پارامتر SQLSVCACCOUNT.

باتوجه به سیاست‌ها نصب می‌توانید از پارامترها دیگری نیز استفاده کنید. بعنوان مثال پارامترهای زیر برای نصب روی سیستمی که نام کاربری و پسورد انرا نداریم مناسب است:
setup.exe /q /Action=Install /Features=SQL /InstanceName=SQLExpress /SECURITYMODE=SQL /SAPWD="1234567" 
/SQLSYSADMINACCOUNTS="Builtin\Administrators" /SQLSVCACCOUNT="NT AUTHORITY\SYSTEM" 
/SQLSVCSTARTUPTYPE="Automatic" /TCPENABLED=1 
نکته: اگر مقدار پارامتر SECURITYMODE برابر SQL باشد حتما باید پارامتر SAPWD مقداردهی شود.
نکته: اگر مقدار TCPENABLED برابر 1 باشد پروتکل TCP/IP فعال می‌شود. اگر هیچ نمونه‌ی دیگری روی سیستم نصب نباشد مقدار TCP Port برابر 1433 است، درغیر اینصورت یک مقدار تصادفی تولید می‌شود.
نکته: برای خوانایی بیشتر، پارامترهای فوق در چند خط نوشته شده اند. برای اجرای صحیح در یک فایل bat، همه انها باید در یک خط باشند.
برای اولین بهتر است از پارامتر HideConsel/ استفاده نکنید تا خطای احتمالی رو مشاهده کنید. برای آپگرید کردن نیز می‌توانید از دستور زیر استفاده کنید:
Setup.exe /q /Hideconsole /ACTION=upgrade /INSTANCENAME=SQLExpress

برای مشاهده دیگر پارامترها به مستندات MSDN مراجعه کنید. همچنین می‌توان نصب از طریق فایل Configuration را نیز انجام داد.
امیدوارم مفید واقع شده باشد.