نظرات مطالب
انجمن سایت LLBLGEN سورس باز شد
با سلام
آقای نصیری به نظر شما آیا LLBLGEN مناسب تر و بهتر از orm های دیگر مثل Entity framework و NHibernate هستش
ممنون می شم یک مقایسه کلی کنید
پاسخ به بازخورد‌های پروژه‌ها
No Entity Framework provider found for the ADO.NET provider
connectionstring تعریف شده پیش فرض را دستکاری کرده اید؟
یا به entity framework 6 اپدیت کردید؟
اگه رشته‌ی اتصالی با نام IrisDbContext را دستکاری نکرده باشید نباید مشکلی داشته باشه.
مطالب
Optimize for unknown

مفهومی در SQL Server وجود دارد به نام parameter sniffing که شرح آن به صورت زیر است.
ابتدا رویه ذخیره شده زیر را در نظر بگیرید:

create procedure test (@pid int)
as
select * from Sales.SalesOrderDetail
where ProductID = @pid
استفاده از کوئری‌های پارامتری یکی از بهترین تمرین‌های کاری با SQL server است؛ از آنجائیکه در این حالت plan تهیه شده مجددا مورد استفاده قرار گرفته، همچنین از SQL injection نیز جلوگیری خواهد کرد، زیرا برای نمونه در مثال فوق تنها pid از نوع int پذیرفته می‌شود و نه هر ورودی خطرناک دیگری.
اما این نوع کوئری‌ها یک مشکل را نیز به همراه خود دارند. این plan تهیه شده به ازای اولین ورودی رویه ذخیره شده تهیه می‌شود (parameter sniffing) و الزامی ندارد که برای دومین ورودی و فراخوانی‌های بعدی، بهترین plan باشد.

برای حل این مشکل راه‌های زیادی هست:
الف) انتساب پارامترهای یک رویه ذخیره شده به متغیری محلی

create procedure test (@pid int)
as
Declare @mpid int
Set @mpid = @pid
select * from Sales.SalesOrderDetail
where ProductID = @mpid
در اینجا پارامتر ورودی مستقیما در کوئری استفاده نشده است و SQL Server این متغیر محلی را sniff نخواهد کرد.

ب) استفاده از گزینه RECOMPILE که سبب خواهد شد به ازای هر ورودی یک plan بهینه تهیه شود. این مورد مصرف CPU بالایی را به همراه خواهد داشت.

ج) راه حل ارائه شده در SQL Server 2005
استفاده از روش الف به علاوه اضافه کردن گزینه کمکی زیر به انتهای اسکریپت فوق

OPTION (OPTIMIZE FOR(@pid = 544))

در اینجا فرض بر این است که می‌دانیم pid=544 بسیار مورد استفاده قرار خواهد گرفت، بنابراین این معرفی را به موتور بهینه ساز SQL Server ارائه خواهیم کرد.

د) راه حل ارائه شده در SQL Server 2008
با استفاده از Optimize for unknown که در اس کیوال سرور 2008 معرفی شده است، مزیت استفاده از کوئری‌های پارامتری همانند استفاده مجدد از plan تهیه شده، حفظ گشته اما این plan‌ تهیه شده اولیه بر اساس اولین مقدار پاس شده، تهیه نگردیده و حالت عمومی‌تر و بهینه‌تری را برای اکثر مقادیر پاس شده خواهد داشت.

create procedure test (@pid int)
as
select * from Sales.SalesOrderDetail
where ProductID = @pid

OPTION(OPTIMIZE FOR (@pid UNKNOWN))

جهت مطالعه بیشتر (+ و + و +)

اشتراک‌ها
انتقال به asp.net core

With the latest release of ASP.NET Core, developers are wondering what the next step is for their web apps and how to convert it over to the new ASP.NET Core.

انتقال به asp.net core
اشتراک‌ها
شناخت NET Core, NETStandard, .NET Core applications and ASP.NET Core

As anyone in the .NET community who hasn't been living under a rock will know, there's a lot of exciting things happening with .NET at the moment with the announcement of the open source, cross platform, .NET Core. However, partly due to the very open nature of its evolution, there's been a whole host of names associated with its development - vNext, ASP.NET 5, ASP.NET Core, .NET generations etc.

In this post I'm going to try and clarify some of the naming and terminology surrounding the evolution of the .NET framework. I'll discuss some of the challenges the latest iteration is attempting to deal with and how the latest developments aim to address these.

This is really for those that have seen some of the big announcements but aren't sure about the intricacies of this new framework and how it relates to the existing ecosystem, which was my situation before I really started digging into it all properly!

Hopefully by the end of this article you'll have a clearer grasp of the latest in .NET! 

شناخت NET Core, NETStandard, .NET Core applications and ASP.NET Core
مطالب
مزیت‌های استفاده از رویه‌های ذخیره شده؛ واقعیت یا توهم؟!

متن زیر یک سری نکات و یا شاید توهماتی را مطرح می‌کند که در مورد رویه‌های ذخیره شده در اس کیوال سرور رایج هستند.

1- رویه‌های ذخیره شده در مقابل SQL Injection مقاوم هستند. کوئری‌های Ad hoc همیشه این آسیب پذیری را به همراه دارند.
نادرست است! رویه‌های ذخیره شده‌ای که رشته‌ها را به صورت پارامتر دریافت کرده و آن‌ها را به صورت یک عبارت sql اجرا می‌کنند، آسیب پذیر هستند. اگر هنگام استفاده از کوئری‌های Ad hoc از پارامترها استفاده شود، در برابر حملات SQL Injection مصون خواهید بود.

2- execution plan رویه‌های ذخیره شده کش می‌شوند اما این Plan برای کوئری‌های Ad hoc هر بار محاسبه و تولید می‌گردد.
نادرست است! اس کیوال سرور تا این اندازه بی هوش نیست! اگر execution plan ایی موجود باشد حتما استفاده خواهد شد و برای موتور اس کیوال سرور اصلا اهمیتی ندارد که کوئری در حال اجرا از یک رویه ذخیره شده صادر شده است یا از یک کوئری Ad hoc . رویه‌های ذخیره شده پیش کامپایل شده نیستند و مانند تمامی کوئری‌های دیگر در زمان اجرا کامپایل می‌شوند.

3- زمانیکه از رویه ذخیره شده استفاده می‌کنید همه چیز را در یک مکان به صورت متمرکز و مجتمع خواهید داشت (مدیریت بهتر)
نادرست است! در یک مکان متمرکز در اختیار شما نیستند. برنامه جای خود را دارد و رویه‌های ذخیره شده در دیتابیس در جای دیگری قرار دارند و برای مثال اگر قرار باشد یک پارامتر را به رویه ذخیره شده خود اضافه کنید، کدهای شما نیز باید تغییر کنند.

4- می‌توان از یک رویه ذخیره شده استفاده مجدد کرد (در نقاط مختلف یک کد) و اعمال تغییرات تنها در یک مکان (دیتابیس) باید صورت گیرد.
هر چند این مورد درست است، اما باید دقت داشت که اگر چندین برنامه از این رویه ذخیره شده استفاده می‌کنند نباید تغییرات شما باعث از کار افتادن سایر برنامه‌ها شوند.

5- می‌توان رویه ذخیره شده را بدون نیاز به توزیع مجدد برنامه تغییر داد.
این مورد تا حدودی صحیح است. اگر تنها بحث بهینه سازی و امثال آن مطرح باشد صحیح است اما اگر واقعا نیاز به تغییر یک کوئری در رویه ذخیره شده وجود داشته باشد به احتمال زیاد برنامه نیز باید دستخوش تغییراتی گردد تا این دو با هم هماهنگ شوند.

نظر شما چیست؟


مطالب
بازنویسی متد مقدار دهی اولیه‌ی کاربر ادمین در ASP.NET Core Identity‌ توسط متد HasData در EF Core
فرض کنید قصد داریم متد «SeedDatabaseWithAdminUserAsync» را توسط روش جدید «مقدار دهی اولیه‌ی بانک اطلاعاتی توسط Entity framework Core» بازنویسی کنیم. در ادامه مراحل اینکار را مرور خواهیم کرد.


اضافه کردن نقش پیش‌فرض Admin

اولین تغییری که در اینجا مورد نیاز است، افزودن نقش پیش‌فرض Admin است. برای این منظور توسط یک IEntityTypeConfiguration جدید، تنظیمات موجودیت سفارشی Role برنامه را به نحو زیر انجام می‌دهیم:
namespace ASPNETCoreIdentitySample.DataLayer.Mappings
{
    public class RoleConfiguration : IEntityTypeConfiguration<Role>
    {
        private readonly SiteSettings _siteSettings;
        private readonly ILookupNormalizer _keyNormalizer;

        public RoleConfiguration(SiteSettings siteSettings, ILookupNormalizer keyNormalizer)
        {
            _siteSettings = siteSettings ?? throw new ArgumentNullException(nameof(siteSettings));
            _keyNormalizer = keyNormalizer ?? throw new ArgumentNullException(nameof(keyNormalizer));
        }

        public void Configure(EntityTypeBuilder<Role> builder)
        {
            builder.ToTable("AppRoles");

            var adminUserSeed = _siteSettings.AdminUserSeed;
            builder.HasData(
                new Role
                {
                    Id = 1,
                    Name = adminUserSeed.RoleName,
                    NormalizedName = _keyNormalizer.NormalizeName(adminUserSeed.RoleName),
                    ConcurrencyStamp = Guid.NewGuid().ToString()
                });
        }
    }
}
در حین افزودن new Role، دو نکته مدنظر قرار گرفته‌اند:
الف) NormalizedName از طریق سرویس ILookupNormalizer در ASP.NET Core Identity تامین می‌شود.
ب) SiteSettings در اینجا جهت دریافت نام نقش Admin از فایل appsettings.json، تعریف شده‌است (تامین مقدار پیش‌فرض).


اضافه کردن کاربر پیش‌فرض Admin

برای اضافه کردن کاربر پیش‌فرض ادمین، علاوه بر سرویس ILookupNormalizer که کار تامین مقادیر NormalizedEmail و NormalizedUserName را به عهده دارد، نیاز به سرویس IPasswordHasher نیز می‌باشد. از آن برای تامین مقدار فیلد PasswordHash، بر اساس سرویس هش کردن پسوردهای توکار ASP.NET Core Identity، استفاده می‌کنیم. برای این منظور توسط یک IEntityTypeConfiguration جدید، تنظیمات موجودیت سفارشی User برنامه را به نحو زیر انجام می‌دهیم:
    public class UserConfiguration : IEntityTypeConfiguration<User>
    {
        private readonly SiteSettings _siteSettings;
        private readonly ILookupNormalizer _keyNormalizer;
        private readonly IPasswordHasher<User> _passwordHasher;

        public UserConfiguration(
            SiteSettings siteSettings,
            ILookupNormalizer keyNormalizer,
            IPasswordHasher<User> passwordHasher)
        {
            _siteSettings = siteSettings ?? throw new ArgumentNullException(nameof(siteSettings));
            _keyNormalizer = keyNormalizer ?? throw new ArgumentNullException(nameof(keyNormalizer));
            _passwordHasher = passwordHasher ?? throw new ArgumentNullException(nameof(passwordHasher));
        }

        public void Configure(EntityTypeBuilder<User> builder)
        {
            builder.ToTable("AppUsers");

            var adminUserSeed = _siteSettings.AdminUserSeed;
            builder.HasData(
                new User
                {
                    Id = 1,
                    UserName = adminUserSeed.Username,
                    NormalizedUserName = _keyNormalizer.NormalizeName(adminUserSeed.Username),
                    Email = adminUserSeed.Email,
                    NormalizedEmail = _keyNormalizer.NormalizeEmail(adminUserSeed.Email),
                    EmailConfirmed = true,
                    IsEmailPublic = true,
                    LockoutEnabled = true,
                    TwoFactorEnabled = false,
                    PasswordHash = _passwordHasher.HashPassword(null, adminUserSeed.Password),
                    ConcurrencyStamp = Guid.NewGuid().ToString(),
                    SecurityStamp = string.Empty,
                    IsActive = true
                });
        }
    }


انتساب دادن نقش Admin، به کاربر Admin

تا اینجا نقش ادمین و کاربر ادمین را به صورت مجزا ایجاد کردیم. مرحله‌ی آخر، انتساب این نقش، به کاربر ادمین است که بر اساس Id این دو صورت می‌گیرد. برای این منظور توسط یک IEntityTypeConfiguration جدید، تنظیمات موجودیت سفارشی UserRole برنامه را به نحو زیر انجام می‌دهیم:
    public class UserRoleConfiguration : IEntityTypeConfiguration<UserRole>
    {
        public void Configure(EntityTypeBuilder<UserRole> builder)
        {
            builder.HasOne(userRole => userRole.Role)
                   .WithMany(role => role.Users)
                   .HasForeignKey(userRole => userRole.RoleId);

            builder.HasOne(userRole => userRole.User)
                   .WithMany(user => user.Roles)
                   .HasForeignKey(userRole => userRole.UserId);

            builder.ToTable("AppUserRoles");

            builder.HasData(
                new UserRole
                {
                    UserId = 1,
                    RoleId = 1
                });
        }
    }


اتصال IEntityTypeConfiguration به DbContext برنامه

IEntityTypeConfigurationهای تهیه شده، دارای سازنده‌هایی هستند که تعدادی سرویس را دریافت می‌کنند. روش معرفی آن‌ها به این صورت است:

الف) تامین دو سرویس ILookupNormalizer و IPasswordHasher در IDesignTimeDbContextFactory تهیه شده:
    public class ApplicationDbContextFactory : IDesignTimeDbContextFactory<ApplicationDbContext>
    {
        public ApplicationDbContext CreateDbContext(string[] args)
        {
            // ....
            services.TryAddScoped<ILookupNormalizer, UpperInvariantLookupNormalizer>();
            services.TryAddScoped<IPasswordHasher<User>, PasswordHasher<User>>();
در حین انجام عملیات Migration، کار به افزودن و اجرای IEntityTypeConfigurationهای تهیه شده می‌رسد و این سرویس‌ها قرار است از DbContext تامین شوند؛ به همین جهت نیاز است روش تامین این سرویس‌ها را در همینجا معرفی کنیم.

ب) پس از تامین این سرویس‌ها، روش معرفی آن‌ها به متدهای modelBuilder.ApplyConfiguration در متد OnModelCreating، توسط متد this.GetService به صورت زیر است. متد this.GetService از فضای نام Microsoft.EntityFrameworkCore.Infrastructure تامین می‌شود و فقط یکبار در زمان Migration از طریق IDesignTimeDbContextFactory تامین خواهد شد:
using Microsoft.EntityFrameworkCore.Infrastructure;

namespace ASPNETCoreIdentitySample.DataLayer.Context
{
    public class ApplicationDbContext :
        IdentityDbContext<User, Role, int, UserClaim, UserRole, UserLogin, RoleClaim, UserToken>,
        IUnitOfWork
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options) { }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            var siteSettings = this.GetService<IOptionsSnapshot<SiteSettings>>()?.Value;
            var lookupNormalizer = this.GetService<ILookupNormalizer>();
            var passwordHasher =  this.GetService<IPasswordHasher<User>>()

            modelBuilder.ApplyConfiguration(new RoleConfiguration(siteSettings, lookupNormalizer));
            modelBuilder.ApplyConfiguration(new UserConfiguration(siteSettings, lookupNormalizer, passwordHasher));
            modelBuilder.ApplyConfiguration(new UserUsedPasswordConfiguration(siteSettings, passwordHasher));
// ...

پس از این تغییرات اگر دستور Migration زیر را صادر کنیم:
dotnet ef migrations --startup-project ../ASPNETCoreIdentitySample/ add V1
مقدار دهی اولیه‌ی نقش و کاربر ادمین و همچنین اتصال این دو را در فایل Migrations\ApplicationDbContextModelSnapshot.cs تولید شده، می‌توان مشاهده کرد.
مطالب
امکانات جدید Entity Framework Designer در VS 2012
ویرایش 2012 ابزار Visual Studio جهت کار با EF امکانات جدیدی دارد که سعی دارم به طور خلاصه چند مورد آنرا توضیح دهم.

پشتیبانی از Enum
در نسخه‌های قبل از EF 5 پیشتیبانی توکاری از Enum‌ها وجود نداشت و برنامه نویس برای استفاده از آن‌ها مجبور بود از روش‌های دیگری استفاده کند؛ مانند ^ استفاده کند. در نسخه 5 این امکان براحتی قابل اعمال است. بدین منظور کافی است:
1- در Designer بر روی خصوصیتی که قصد تبدیل آنرا به enum دارید راست کلیک کرده و گزینه Convert to enum را انتخاب کنید.

2- در پنجره Add enum ابتدا در قسمت Underlying type نوع Int32 را انتخاب کنید سپس می‌توان نام enum و اعضای آنرا و تعیین کرد.

3- دکمه ok را کلیک کنید و سپس پروژه را Build کنید.
در ادامه به راحتی می‌توان از آن در برنامه به صورت زیر استفاده کرد:
var department = (from d in context.Departments
                        where d.Name == DepartmentNames.English
                        select d).FirstOrDefault();

تقسیم یک مدل در Entity Framework به چند دیاگرام 
هنگامی که یک دیاگرام جدید ایجاد می‌کنید این دیاگرام به طور پیش فرض با نام Diagram1 به پوشه Diagrams اضافه می‌شود. اطلاعات مربوط به ظاهر موجودیت مانند رنگ و شکل و روابط آنها نیز در فایلی با پسوند edmx.diagram قرار می‌گیرند. شما بصورت دستی نمی‌توانید این فایل را تغییر دهید چون اطلاعات آن دوباره توسط جنریتور رونویسی می‌شود. لذا تغییر در دیاگرام به روش دستی مورد اطمینان نیست!

 
حتما برای کسانیکه از EF ِDesigner استفاده می‌کنند پیش آمده که بخواهند مدل موجویت هایشان را بجای یک فایل در چند فایل قرار دهند. اینکار مخصوصا زمانی که تعداد موجودیت‌ها زیاد است لازم به نظر می‌رسد بعلاوه اینکه مدیریت و مرور موجودیت‌ها را در پروژهای بزرگ آسانتر می‌کند. خوشبختانه این امکان در Visual Studio 2012 ایجاد شده است. 
بدین منظور در دیاگرام برنامه موجودیت هایی را که می‌خواهید به دیاگرام دیگری انتقال دهید با کلیک و شیفت انتخاب کنید. سپس راست کلیک کرده و گزینه Move to new Diagram را انتخاب کنید. دیاگرام جدیدی ایجاد شده و موجودیت انتخاب شده به آنجا انتقال داده می‌شود. بهتر است موجودیت هایی که برای انتقال انتخاب کرده اید به صورت یک گروه مستقل باشند یعنی با موجودیت‌های دیگر رابطه نداشته باشند.
کار انتقال به یک دیاگرام جدید را می‌توان به کمک کلیدهای Ctrl+C و Ctrl+X نیز انجام داد، باید توجه داشت در حالتی که موجودیت را کپی می‌کنید، نام موجودیت جدید با اضافه شدن یک عدد از موجودیت موجود جدا می‌شود.

تغییر رنگ موجودیت
روش دیگری که جهت متمایز و جدا کردن موجودیت‌ها می‌توان از آن استفاده کرد، تغییر رنگ آنهاست. بدین منظور پس از انتخاب موجودیت‌ها می‌توانید با تغییر مقدار Fill Color در پنجره Properties رنگ موجودیت‌های انتخاب شده را تغییر داد.