مشکل مهم این روش عدم سازگاری کامل آن با EF است. برای مثال در آن تفاوتی بین (Include(x=>x.Tags و (Include(x=>x.Users وجود ندارد. به همین جهت در این نوع موارد، قادر به تولید کلید منحصربفردی جهت کش کردن اطلاعات یک کوئری مشخص نیست. در اینجا یک کوئری LINQ، به معادل رشتهای آن تبدیل میشود و سپس Hash آن محاسبه میگردد. این هش، کلید ذخیره سازی اطلاعات حاصل از کوئری، در سیستم کش خواهد بود. زمانیکه دو کوئری Include دار متفاوت EF، هشهای یکسانی را تولید کنند، عملا این سیستم کش، کارآیی خودش را از دست میدهد. برای رفع این مشکل پروژهی دیگری به نام EF cache ارائه شدهاست. این پروژه بسیار عالی طراحی شده و میتواند جهت ایده دادن به تیم EF نیز بکار رود. اما در آن فرض بر این است که شما میخواهید کل سیستم را در یک کش قرار دهید. وارد مکانیزم DBCommand و DataReader میشود و در آنجا کار کش کردن تمام کوئریها را انجام میدهد؛ مگر آنکه به آن اعلام کنید از کوئریهای خاصی صرفنظر کند.
با توجه به این مشکلات، روش بهتری برای تولید هش یک کوئری LINQ to Entities بر اساس کوئری واقعی SQL تولید شده توسط EF، پیش از ارسال آن به بانک اطلاعاتی به صورت زیر وجود دارد:
private static ObjectQuery TryGetObjectQuery<T>(IQueryable<T> source) { var dbQuery = source as DbQuery<T>; if (dbQuery != null) { const BindingFlags privateFieldFlags = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public; var internalQuery = source.GetType().GetProperty("InternalQuery", privateFieldFlags) .GetValue(source); return (ObjectQuery)internalQuery.GetType().GetProperty("ObjectQuery", privateFieldFlags) .GetValue(internalQuery); } return null; }
این اطلاعات، پایهی تهیهی کتابخانهی جدیدی به نام EFSecondLevelCache گردید. برای نصب آن کافی است دستور ذیل را در کنسول پاورشل نیوگت صادر کنید:
PM> Install-Package EFSecondLevelCache
var products = context.Products.Include(x => x.Tags).FirstOrDefault();
var products = context.Products.Include(x => x.Tags).Cacheable().FirstOrDefault(); // Async methods are supported too.
پس از آن نیاز است کدهای کلاس Context خود را نیز به نحو ذیل ویرایش کنید (به روز رسانی شدهی آن در اینجا):
namespace EFSecondLevelCache.TestDataLayer.DataLayer { public class SampleContext : DbContext { // public DbSet<Product> Products { get; set; } public SampleContext() : base("connectionString1") { } public override int SaveChanges() { return SaveAllChanges(invalidateCacheDependencies: true); } public int SaveAllChanges(bool invalidateCacheDependencies = true) { var changedEntityNames = getChangedEntityNames(); var result = base.SaveChanges(); if (invalidateCacheDependencies) { new EFCacheServiceProvider().InvalidateCacheDependencies(changedEntityNames); } return result; } private string[] getChangedEntityNames() { return this.ChangeTracker.Entries() .Where(x => x.State == EntityState.Added || x.State == EntityState.Modified || x.State == EntityState.Deleted) .Select(x => ObjectContext.GetObjectType(x.Entity.GetType()).FullName) .Distinct() .ToArray(); } } }
کدهای کامل این پروژه را از مخزن کد ذیل میتوانید دریافت کنید:
EFSecondLevelCache
پ.ن.
این کتابخانه هم اکنون در سایت جاری در حال استفاده است.
- تمامی پیامهای دریافتی در یک Partition از یک Topic، به همان ترتیبی که دریافت میشوند ذخیره میشوند.
- Consumerها تمامی پیامها را در یک Partition به همان ترتیبی که ذخیره شدهاند، دریافت میکنند.
- در یک Topic با Replication Factorی با مقدار N، درجه تحمل خطا N - 1 میباشد.
در این قسمت تلاش میکنم در خصوص محیط BIMS (Business Intelligence Management Studio) و همچنین AdventureWorksDW2008R2 توضیحاتی را ارائه کنم. در ابتدا در خصوص طراحی انجام شده در Data Warehouse مربوط به پایگاه دادهی Adventure Works 2008 توضیحاتی ارایه میگردد.
شاید بهترین کار در خصوص آشنایی با یک پایگاه داده نگاه کردن به دیاگرام کلی آن پایگاه داده باشد. بنابر این در ابتدا میبایست یک دیاگرام از پایگاه دادهی AdventureWorksDW2008R2 بسازیم (این کار را در SQL Server Management Studio انجام میدهیم) . قبل از ساخت دیاگرام میبایست کاربر Sa را به عنوان Owner پایگاه داده معرفی کنیم.
برای این منظور ابتدا Properties پایگاه دادهی AdventureWorksDW2008R2 را گرفته و به قسمت Files رفته و با انتخاب دکمهی ... در مقابل Owner و جستجوی کاربر Sa ، اقدام به مشخص کردن مالک پایگاه داده میکنیم. و سپس دکمهی Ok را میزنیم.
مطابق شکل زیر
سپس یک دیاگرام کلی از پایگاه داده تولید میکنیم. مانند شکل زیر
با یک نگاه اجمالی مشخص میگردد که نام تمامی جداول پایگاه دادهی DW یا با کلمهی Dim یا با کلمهی Fact شروع شدهاند.
همان طور که در مقالهی شمارهی یک نیز عنوان شد، چندین روش طراحی DW وجود دارد :
1. ستاره ای
2. دانه برفی
3. کهکشانی
دقت داشته باشید که جداول Fact دارای فیلدهای عددی نیز میباشد که توسط مراحل ETL پر شدهاند و جداول Dimension دارای ابعادی هستند که به شاخصهای موجود در یک جدول Fact معنا میدهند. به عبارت دیگر شاخص میزان فروش اینترنتی، یک Measure میباشد. اما با ارایه دو دایمنشن، به یک واکشی، عملا ما یک Measure داریم که بر اساس آن دو بعد، ماهیت پیدا کرده است. به عنوان مثال میزان فروش اینترنتی بر اساس سال و ماه و روز و براساس کشور خریدار مشخص میشود.
یکی از روشهای تهیهی DW این میباشد که کاربران خبره در هر سیستم، مشخص نمایند چه گزارشاتی مورد نظر آنها میباشد. سپس توسط تیم پشتیبانی آن سیستمها، جداول Fact,Dimension مورد نیاز برای حصول گزارش مربوطه تهیه گردد.
شاید ذکر این نکته جالب باشد که برای توسعهی یک پایگاه دادهی Multidimensional توسط Solution های ماکروسافت نیازی به آشنایی با یک محیط کار ( IDE ) جدید نمیباشد. همان طور هم که در مقالهی قبلی اشاره شد، برای Deploy کردن یک پایگاه دادهی چند بعدی ( Multidimensional ) از خود محیط Visual Studio .Net استفاده میشود. بنابر این آن دسته از برنامه نویسانی که با این محیط آشنا میباشند به راحتی میتوانند به توسعهی پایگاه دادهی چند بعدی بپردازند.
لازم به ذکر میباشد که اساسا هدف من از شروع این سری مقالات ، آموزش MDX Query ها میباشد و نه آموزش BIMS ، با این وجود در این قسمت و در قسمت بعدی، توضیحات مقدماتی کار با BIMS ارایه میگردد و همچنین در فرصت مناسب در خصوص BIMS یک مجموعه مقالهی جامع ارایه خواهم کرد.
در ابتدا اجزا BIMS را برای شما توضیح میدهم و سپس در خصوص ساخت هر کدام از آنها و ترتیب ساخت آنها توضیحاتی ارایه خواهم داد.
مسیر باز کردن برنامهی SQL Server Business Intelligence Development Studio = BIDS در زیر آمده است:
C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Microsoft SQL Server 2012\ SQL Server Data Tools
دقت داشته باشید که در صورت استفاده از نسخهی Sql Server 2008 میبایست مسیر زیر را جستجو نمایید:
C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Microsoft SQL Server 2008 R2
با نگاه کردن به محیط BIMS می توانید پنجرهی Solution Explorer را مشاهده کنید .(در صورت عدم مشاهده، میتوانید این پنجره را از منوی View باز کنید)
در پنجرهی Solution Explorer ابتدا نام Solution و در زیر آن، نام پروژه را خواهیم دید (نام پروژه و نام پایگاه دادهی چند بعدی، مشابه یکدیگر میباشند) و در زیر نام پروژه، موارد زیر را میبینیم:
1. Data Source
2. Data Source View
3. Cubes
4. Dimensiones
5. ….
Data Source : عملا برقرار کنندهی پروژه با Data Warehouse میباشد. دقت داشته باشید که امکان تهیه یک پایگاه دادهی چند بعدی از چندین DW وجود دارد و حتا نوع DW ها میتواند متفاوت باشد (به عبارت دیگر ما میتوانیم چندین DW در RDBMS های متفاوت داشته باشیم و همهی آنها را در یک Multidimensional Database تجمیع کنیم). برای انجام چنین کاری باید چندین Data Source تعریف کنیم.
Data Source View : هر Data Source میتواند دارای چندین تقسیم بندی با مفاهیم Business ی باشد. برای هر کدام از این دسته بندیها میتوانیم یک یا چند Data Source View ایجاد کنیم . به عبارت دیگر ایجاد Data Source View ها سبب خلاصه شدن تعداد جداول Fact , Dimension براساس یک بیزینس خاص میباشد و در ادامه راحتتر میتوانیم Cube ها را تولید کنیم.
نکته: جداول Fact , Dimension در ساختار D ata Warehouse ساخته میشوند.
Cubes : محل تعریف Cube ها در این قسمت میباشد. در سری آموزش SSAS در خصوص نحوهی ساخت Cube ها شرح کاملی ارایه خواهم کرد.
Dimensions : با توجه به این که در روال ساخت Cube ما مشخص میکنیم چه Dimension هایی داریم، یک سری از Dimension ها به صورت پیش فرض در این قسمت قرار میگیرند و البته در صورت تغییر در Data Source View میتوانیم یک Dimension را به صورت دستی در این قسمت ایجاد نماییم و سپس آن را به Cube مورد نظر اضافه نماییم.
دقت داشته باشید که برای ساخت یک پروژه میبایست بعد از ساخت Data Warehouse در برنامهی BIMS اقدام به ساخت یک Data Source کنیم و سپس با توجه به Businessهای موجود در سیستمهای OLTP اقدام به ساخت Data Source Viewهای مناسب کرده و در نهایت اقدام به ساخت Cube کنیم. بعد از انجام تنظیمات مختلف در Cube مانند ساخت Hierarchy , KPI و ... نیاز میباشد که پروژه را Deploy کنیم تا پایگاه دادهی چند بعدی (MDB) ساخته شود.
در قسمت بعدی نحوهی ساخت یک پروژه در SSAS و چگونگی باز کردن یک پایگاه داده را بررسی خواهیم کرد.
افزونهی زیر کار مشخص کردن کلماتی که قابل تبدیل از فارسی به پارسی هستند را انجام میدهد (به صورت خودکار و در زمان تایپ) و همچنین امکان تبدیل خودکار آنها را نیز فراهم میکند.
برای نصب آن باید به ترتیب زیر عمل کنید (مهم)
- نصب دات نت فریم ورک 3 و نیم (نزدیک به 231 مگابایت)
اگر VS.Net 2008 SP1 را دارید نیازی به این بسته نخواهید داشت.
- نصب بسته به روز رسانی سیستم (حدودا 14 مگ)
- نصب افزونه (حدودا 550 کیلوبایت)
لطفا این سه مرحله را به ترتیب انجام دهید در غیر اینصورت نتیجه نخواهید گرفت.
همچنین بدیهی است که برنامه باید با دسترسی admin نصب شود.
و همانطور که در عنوان این موضوع نیز ذکر گردید، این افزونه تنها برای MS-Word 2007 طراحی شده است.
سورس کامل و جزئیات نحوهی برنامه نویسی آنرا در طی روزهای آینده در این بلاگ مشاهده خواهید کرد.
پس از نصب به گزینهی word options مراجعه کنید: (جهت اطمینان از نصب آن)
این افزونه را باید در لیست مربوطه مشاهده نمائید:
namespace OpenAPISwaggerDoc.Web.Controllers { [Route("api/[controller]")] [ApiController] public class ConventionTestsController : ControllerBase { // GET: api/ConventionTests/5 [HttpGet("{id}", Name = "Get")] [ApiConventionMethod(typeof(DefaultApiConventions), nameof(DefaultApiConventions.Get))] public string Get(int id) { return "value"; }
using Microsoft.AspNetCore.Mvc.ApiExplorer; namespace Microsoft.AspNetCore.Mvc { public static class DefaultApiConventions { [ApiConventionNameMatch(ApiConventionNameMatchBehavior.Prefix)] [ProducesDefaultResponseType] [ProducesResponseType(200)] [ProducesResponseType(404)] public static void Get( [ApiConventionNameMatch(ApiConventionNameMatchBehavior.Suffix)] [ApiConventionTypeMatch(ApiConventionTypeMatchBehavior.Any)] object id); } }
امکان اعمال DefaultApiConventions به تمام متدهای یک کنترلر API نیز به صورت زیر با استفاده از ویژگی ApiConventionType اعمال شدهی به کلاس کنترلر میسر است:
namespace OpenAPISwaggerDoc.Web.Controllers { [Route("api/[controller]")] [ApiController] [ApiConventionType(typeof(DefaultApiConventions))] public class ConventionTestsController : ControllerBase
[assembly: ApiConventionType(typeof(DefaultApiConventions))] namespace OpenAPISwaggerDoc.Web { public class Startup
ایجاد ApiConventions سفارشی
همانطور که عنوان شد، اگر متدهای API شما دقیقا همان نامهای پیشفرض Get/Post/Put/Delete را داشته باشند، توسط DefaultApiConventions مدیریت خواهند شد. در سایر حالات، مثلا اگر بجای نام Post، از نام Insert استفاده شد، باید ApiConventions سفارشی را ایجاد کرد:
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ApiExplorer; namespace OpenAPISwaggerDoc.Web.AppConventions { public static class CustomConventions { [ProducesDefaultResponseType] [ProducesResponseType(StatusCodes.Status201Created)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ApiConventionNameMatch(ApiConventionNameMatchBehavior.Prefix)] public static void Insert( [ApiConventionNameMatch(ApiConventionNameMatchBehavior.Any)] [ApiConventionTypeMatch(ApiConventionTypeMatchBehavior.Any)] object model) { } } }
پس از آن برای اعمال این ApiConventions جدید میتوان به صورت زیر عمل کرد:
namespace OpenAPISwaggerDoc.Web.Controllers { [Route("api/[controller]")] [ApiController] public class ConventionTestsController : ControllerBase { [HttpPost] [ApiConventionMethod(typeof(CustomConventions), nameof(CustomConventions.Insert))] public void Insert([FromBody] string value) { }
سؤال: آیا استفادهی از این ApiConventions ایدهی خوبی است؟
همانطور که در ابتدای بحث نیز عنوان شد، اگر فیلترهای سراسری را مانند قسمت قبل فعال کرده باشیم، از اعمال ApiConventions صرفنظر میشود. همچنین حالت پیشفرض آنها برای حالتهای متداول و ساده مفید هستند و برای سایر حالات باید کدهای زیادی را نوشت. به همین جهت خود مایکروسافت هم استفادهی از ApiConventions را صرفا برای کنترلرهای API ای که دقیقا مطابق با قالب پیشفرض آنها تهیه شدهاند، توصیه میکند. بنابراین استفادهی از Attributes که در قسمت قبل آنها را بررسی کردیم، مقدم هستند بر استفادهی از ApiConventions و تعدادی از بهترین تجربههای کاربری در این زمینه به شرح زیر میباشند:
- از API Analyzers که در قسمت قبل معرفی شد، برای یافتن کمبودهای نقایص مستندات استفاده کنید.
- از ویژگی ProducesDefaultResponseType استفاده کنید؛ اما تا جائیکه میتوانید، جزئیات ممکن را به صورت صریحی مستند نمائید.
- Attributes را به صورت سراسری معرفی کنید.
بهبود مستندات Content negotiation
فرض کنید میخواهید لیست کتابهای یک نویسنده را دریافت کنید. در اینجا خروجی ارائه شده، با فرمت JSON تولید میشود؛ اما ممکن است XML ای نیز باشد و یا حالتهای دیگر، بسته به تنظیمات برنامه. کار Content negotiation این است که مصرف کنندهی یک API، دقیقا مشخص کند، چه نوع فرمت خروجی را مدنظر دارد. هدری که برای این منظور استفاده میشود، accept header نامدارد و ذکر آن اجباری است؛ هر چند تعدادی از APIها بدون وجود آن نیز سعی میکنند حالت پیشفرضی را ارائه دهند.
Swagger-UI به نحوی که در تصویر فوق ملاحظه میکنید، امکان انتخاب Accept header را مسیر میکند. در این حالت اگر application/json را انتخاب کنیم، خروجی JSON ای را دریافت میکنیم. اما اگر text/plain را انتخاب کنیم، چون توسط API ما پشتیبانی نمیشود، خروجی از نوع 406 یا همان Status406NotAcceptable را دریافت خواهیم کرد. بنابراین وجود گزینهی text/plain در اینجا غیرضروری و گمراه کنندهاست و نیاز است این مشکل را برطرف کرد:
namespace OpenAPISwaggerDoc.Web.Controllers { [Produces("application/json")] [Route("api/authors/{authorId}/books")] [ApiController] public class BooksController : ControllerBase
پس از اعمال این ویژگی، تاثیر آنرا بر روی Swagger-UI در شکل زیر مشاهده میکنید که اینبار تنها به یک مورد مشخص، محدود شدهاست:
در اینجا اگر قصد داشته باشیم خروجی XML را نیز پشتیبانی کنیم، میتوان به صورت زیر عمل کرد:
- ابتدا در کلاس Startup، نیاز است OutputFormatter متناظری را به سیستم معرفی نمود:
namespace OpenAPISwaggerDoc.Web { public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddMvc(setupAction => { setupAction.OutputFormatters.Add(new XmlSerializerOutputFormatter());
namespace OpenAPISwaggerDoc.Web.Controllers { [Produces("application/json", "application/xml")] [Route("api/authors/{authorId}/books")] [ApiController] public class BooksController : ControllerBase
در این حالت اگر Controls Accept header را در UI از نوع xml انتخاب کنیم و سپس با کلیک بر روی دکمهی try it out و ذکر id یک نویسنده، لیست کتابهای او را درخواست کنیم، خروجی نهایی XML ای آن قابل مشاهده خواهد بود:
البته تا اینجا فقط Swagger-UI را جهت محدود کردن به دو نوع خروجی با فرمت JSON و XML، اصلاح کردهایم؛ اما این مورد به معنای محدود کردن سایر ابزارهای آزمایش یک API مانند postman نیست. در این نوع موارد، تمام مدیاتایپهای ارسالی پشتیبانی نشده، سبب تولید خروجی با فرمت JSON میشوند. برای محدود کردن آنها به خروجی از نوع 406 میتوان تنظیم ReturnHttpNotAcceptable را به true انجام داد تا اگر برای مثال درخواست application/xyz ارسال شد، صرفا یک استثناء بازگشت داده شود و نه خروجی JSON:
namespace OpenAPISwaggerDoc.Web { public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddMvc(setupAction => { setupAction.ReturnHttpNotAcceptable = true; // Status406NotAcceptable
بهبود مستندات نوع بدنهی درخواست
تا اینجا فرمت accept header را دقیقا مشخص و مستند کردیم؛ اما اگر به تصویر فوق دقت کنید، در حین ارسال اطلاعاتی از نوع POST به سرور، چندین نوع Request body را میتوان انتخاب کرد که الزاما تمام آنها توسط API ما پشتیبانی نمیشود. برای رفع این مشکل میتوان از ویژگی Consumes استفاده کرد که نوع مدیتاتایپهای مجاز ورودی را مشخص میکند:
namespace OpenAPISwaggerDoc.Web.Controllers { [Produces("application/json", "application/xml")] [Route("api/authors/{authorId}/books")] [ApiController] public class BooksController : ControllerBase { /// <summary> /// Create a book for a specific author /// </summary> /// <param name="authorId">The id of the book author</param> /// <param name="bookForCreation">The book to create</param> /// <returns>An ActionResult of type Book</returns> [HttpPost()] [Consumes("application/json")] [ProducesResponseType(StatusCodes.Status201Created)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task<ActionResult<Book>> CreateBook( Guid authorId, [FromBody] BookForCreation bookForCreation) {
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید: OpenAPISwaggerDoc-05.zip
در این قسمت میتوانید هر کدام از موارد را که نیاز دارید، نصب کنید. هر کدام از عنوانها در آینده آموزش داده خواهند شد و پیشنهاد میشود آنها را نصب کنید؛ در غیر این صورت فقط گزینهی اول کافی میباشد.
در صورت کلیک بر روی Options، با صفحهی زیر روبرو میشوید که در آن با انتخاب گزینهی Administrative، میتوانید تنظیمات بیشتری را در زمان نصب، انجام دهید و همچنین با انتخاب All users ، نرم افزار برای تمام کاربران سیستم در دسترس خواهد بود.
بعد از اتمام نصب، فایلهای نرم افزار در آدرس زیر در دسترس میباشند:
%LOCALAPPDATA%\JetBrains\Installations
اکنون اگر Visual studio را باز کنید، Resharper به قسمت Extensionsها اضافه شدهاست که در ادامهی آموزش به بررسی آن میپردازیم.
زبانهای پشتیبانی شده
ریشارپر از زبان های C# , VB.NET , TypeScript , JavaScript , C++ , CSS پشتیبانی میکند.
افزایش سرعت Reshaper
یکی از مشکلاتی که بیشتر افراد بعد از نصب این افزونه دارند، مخصوصا اگر سیستم آنها خیلی قوی نباشد، کند شدن Visual Studio میباشد. برای سریعتر کردن این افزونه راه هایی موجود میباشد که به آنها میپردازیم.
- خود ریشارپر پیشنهادهایی را برای بهبود سرعت میکند که آنها در مسیر زیر در دسترس میباشند:
ReSharper | Options | Environment | Performance Guide
- یکی از امکانات ریشارپر، نشان دادن تمام خطاهای موجود در برنامه به صورت یک لیست میباشد که نام این ویژگی، solution-wide analysis است و البته این امکان باعث سنگینی زیاد Visual studio میشود. برای غیر فعال کردن آن میتوانید به مسیر زیر بروید:
ReSharper | Options | Code Inspection | Settings
- راه دیگر انجام اینکار از قسمت تنظیمات خود Visual studio است. برای این کار به مسیر زیر بروید و گزینههای گفته شده را غیر فعال کنید.
Environment | General
Automatically adjust visual experience based on client performance Enable rich client visual experience
- همچنین این گزینه را نیز فعال کنید تا جلوی لگ در UI گرفته شود.
Use hardware graphics acceleration if available
- اگر پروژهی بزرگی را دارید، میتوانید گزینهی زیر را نیز غیر فعال کنید. البته با غیر فعال کردن این گزینه در صورت کرش نرم افزار، کدهای ذخیره نشده ازدست میروند.
Environment | AutoRecover
Save AutoRecover information
- اگر با تعداد فایلهای زیادی کار میکنید، امکان Track changes باعث کندی برنامه میشود. برای غیر فعال کردن این گزینه، به مسیر زیر بروید.
Text Editor | General
Track changes
- خود Visual studio گزینههایی را مانند خطاها در Scroll Bar نشان میدهد که این امکانات در ریشارپر هم موجود میباشد. برای غیر فعال کردن این امکان در Visual Studio برای جلوگیری از دو بار نشان دادن اطلاعات، به مسیر زیر بروید و گزینهی گفته شده را غیر فعال کنید.
Text Editor | All Languages | Scroll Bars
Show annotations over vertical scroll bar
- یکی دیگر از امکانات Visual Studio گزینهای به اسم CodeLens می باشد که یکی از کارهای آن، نشان دادن تمام رفرنسهای توابع یک فایل، در بالای تابع میباشد. این امکان نیز باعث کندی بسیار زیاد برنامه میشود. برای غیر فعال کردن آن میتوانید به مسیر زیر بروید.
Text Editor | All Languages | CodeLens
- هم Visual Studio و هم Reshaper کدهای شما را Format میکنند. پس برای جلوگیری از دوبار انجام شدن این کار، به مسیر زیر بروید و گزینهی گفته شده را غیر فعال کنید.
Text Editor | [Language] | Formatting
auto-formatting
- اگر از تمام امکانات Reshaper نمیخواهید استفاده کنید، میتوانید آنها را از آدرس زیر غیر فعال کنید.
Environment | Products & Features
- اگر در زمان تایپ کردن، برنامه کند میباشد، میتوانید بعضی از امکانات Resharper را از آدرس زیر غیر فعال کنید.
Environment | IntelliSense
Completion Appearance ReSharper's IntelliSense for specific languages
_identityVerifier.Initialize(); var isValidIdentity = _identityVerifier.Validate( application.Applicant.Name, application.Applicant.Age, application.Applicant.Address);
_creditScorer.CalculateScore(application.Applicant.Name, application.Applicant.Address); if (_creditScorer.Score < MinimumCreditScore) { return application.IsAccepted; }
تنظیم مقدار خاصیت Score شیء Mock شده
اینترفیس ICreditScorer به صورت زیر تعریف شدهاست و دارای خاصیت Score میباشد که مقدار عددی آن با مقدار حداقل اعتبار تنظیم شدهی در کلاس LoanApplicationProcessor مقایسه خواهد شد (MinimumCreditScore = 100_000):
namespace Loans.Services.Contracts { public interface ICreditScorer { int Score { get; } void CalculateScore(string applicantName, string applicantAddress); } }
var mockCreditScorer = new Mock<ICreditScorer>(); mockCreditScorer.Setup(x => x.Score).Returns(110_000);
اکنون اگر متد آزمایش واحد Accept را بررسی کنیم، چون شخص درخواست دهنده، دارای اعتبار بیشتری از حداقل اعتبار مورد نیاز است، این آزمایش با موفقیت به پایان خواهد رسید. اگر این تنظیم صورت نمیگرفت، شیء mockCreditScorer، مقدار پیشفرض int یا همان صفر را به عنوان مقدار Score بازگشت میداد.
تنظیم مقادیر خواص تو در تو و سلسله مراتبی اشیاء Mock شده
برای کار با خواص تو در تو، ابتدا دو مدل زیر را ایجاد میکنیم:
namespace Loans.Models { public class ScoreResult { public ScoreValue ScoreValue { get; } } public class ScoreValue { public int Score { get; } } }
using Loans.Models; namespace Loans.Services.Contracts { public interface ICreditScorer { int Score { get; } void CalculateScore(string applicantName, string applicantAddress); ScoreResult ScoreResult { get; } } }
//if (_creditScorer.Score < MinimumCreditScore) if (_creditScorer.ScoreResult.ScoreValue.Score < MinimumCreditScore)
برای رفع این مشکل در متد آزمون واحد Accept، باید به صورت زیر عمل کرد:
var mockCreditScorer = new Mock<ICreditScorer>(); mockCreditScorer.Setup(x => x.Score).Returns(110_000); var mockScoreValue = new Mock<ScoreValue>(); mockScoreValue.Setup(x => x.Score).Returns(110_000); var mockScoreResult = new Mock<ScoreResult>(); mockScoreResult.Setup(x => x.ScoreValue).Returns(mockScoreValue.Object); mockCreditScorer.Setup(x => x.ScoreResult).Returns(mockScoreResult.Object);
سپس یک سطح بالاتر را یعنی ScoreResult را تنظیم خواهیم کرد. در اینجا نیاز است خاصیت ScoreValue آن به mock object قبلی تنظیم شود. به همین جهت Returns آن به خاصیت Object شیء mockScoreValue، تنظیم شدهاست.
در آخر برای تنظیم خاصیت ScoreResult شیء mockCreditScorer اصلی، از شیء mockScoreResult استفاده خواهیم کرد.
در این حالت اگر متد آزمون واحد Accept را اجرا کنیم، اینبار به خطای زیر برخواهیم خورد:
Test method Loans.Tests.LoanApplicationProcessorShould.Accept threw exception: System.NotSupportedException: Unsupported expression: x => x.Score Non-overridable members (here: ScoreValue.get_Score) may not be used in setup / verification expressions.
namespace Loans.Models { public class ScoreResult { public virtual ScoreValue ScoreValue { get; } } public class ScoreValue { public virtual int Score { get; } } }
ساده سازی روش تنظیم مقادیر خواص تو در تو و سلسله مراتبی اشیاء Mock شده
روش دیگری نیز برای تنظیم مقادیر خواص تو در تو در کتابخانهی Moq وجود دارد:
mockCreditScorer.Setup(x => x.ScoreResult.ScoreValue.Score).Returns(110_000);
بدیهی است در این حالت نیز باید شرط virtual بودن این خواص، برقرار باشد؛ در غیراینصورت همان استثنای NotSupportedException را دریافت خواهیم کرد.
یک نکته: اگر در زمان تشکیل یک Mock object، مقدار خاصیت DefaultValue آنرا به صورت زیر تنظیم کنیم:
var mockCreditScorer = new Mock<ICreditScorer> { DefaultValue = DefaultValue.Mock };
بررسی تغییرات مقادیر خواص اشیاء Mock شده
کتابخانهی Moq، امکان ردیابی تغییرات مقادیر خواص اشیاء Mock شده را نیز داراست. برای نمایش آن، فرض کنید خاصیت جدید Count را به اینترفیس ICreditScorer اضافه کردهایم:
using Loans.Models; namespace Loans.Services.Contracts { public interface ICreditScorer { int Score { get; } void CalculateScore(string applicantName, string applicantAddress); ScoreResult ScoreResult { get; } int Count { get; set; } } }
_creditScorer.CalculateScore(application.Applicant.Name, application.Applicant.Address); _creditScorer.Count++;
Assert.AreEqual(1, mockCreditScorer.Object.Count);
برای فعال سازی ردیابی تغییرات مقادیر خاصیت Count، تنها کافی است آنرا توسط متد SetupProperty، معرفی کنیم:
mockCreditScorer.SetupProperty(x => x.Count);
در اینجا میتوان یک مقدار اولیه را هم درنظر گرفت:
mockCreditScorer.SetupProperty(x => x.Count, 10);
فعالسازی بررسی تغییرات تمام مقادیر خواص اشیاء Mock شده
اگر تعداد خواصی که قرار است مورد ردیابی قرارگیرند زیاد است، بجای فراخوانی متد SetupProperty بر روی تک تک آنها، میتوان تمام آنها را به صورت زیر تحت کنترل قرار داد:
mockCreditScorer.SetupAllProperties();
نکتهی مهم: محل قرارگیری SetupAllProperties مهم است. برای مثال اگر این سطر را پس از سطر تنظیم مقدار پیشفرض x.ScoreResult.ScoreValue.Score قرار دهید، آزمایش با شکست مواجه میشود؛ چون تنظیمات بازگشت مقادیر پیشفرض خواص را به طور کامل بازنویسی میکند. بنابراین این سطر باید پیش از سطر تنظیم مقادیر پیشفرض خواص Mock شده، فراخوانی شود تا بر روی این مقادیر تنظیمی، تاثیری نداشته باشد.
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید: MoqSeries-03.zip
- Convert.Net
- Regular Expression Tester : که جهت تست Regexهای نوشته شده استفاده میشود.
- Encoding & Decoding : جهت تبدیل انواع رشتههای Encoded ویا Decoded به یکدیگر استفاده میشود و از html - url - EScape-js - Base64 - string و ... پشتیبانی میکند.
- Encryption & Decryption : جهت Encrypt و Decrypt انواع رشته استفاده میشود که از انکریپتورهای معروفی همچون AES - Rijndael - DES - SHA - TripleDES پشتیبانی میکند.
- Language Translation : یک دیکشنری Multi Language آنلاین در اختیار شما برای ترجمه متون قرار میدهد.
- C# & VB.Net Convertor : برای تبدیل کدهای C# به Vb و برعکس استفاده میشود و طبق تست هایی که روش به شخصه انجام دادم در اکثر موارد بدون خطا تا حدود 90 درصد تبدیلات رو به صورت موفق انجام میده ولی مانند سایر Convertorها با Lambda Expression کمی مشکل دارد.
- Xml & Json Browser : برای مشاهده و تبدیل Xml به Json و برعکس بسیار مفید است ..
- Linq Tester : برای تست کوئریهای Linq استفاده میشود . (برای استفاده از این امکان باید Roslyne روی سیستم شما نصب باشد)
- Database.Net
SQL Server 2000/2005/2008/2012/2014/Express/LocalDB SQL Server Compact 3.1/3.5/4.0 (*.sdf;*.*) SQL Azure 10/11 MS Access 97/2000/2002/2003 (*.mdb;*.mde;*.*), 2007/2010/2013 (*.accdb;*.accde;*.*) MS Excel 97/2000/2002/2003(*.xls;*.*), 2007/2010/2013 (*.xlsx;*.xlsm;*.xlsb;*.*) Firebird SuperServer/Embedded 1.5/2.0/2.1/2.5 (*.gdb;*.fdb;*.*) SQLite 3.x (*.db;*.db3;*.sqlite;*.*) MySQL 5.x, MariaDB 5.x/10.x PostgreSQL 8.x/9.x Oracle 10g/11g/12c IBM DB2 9.x/10.x IBM Informix 11.x/12.x Sybase ASE 15.x dBASE IV (*.dbf) Visual FoxPro (*.dbc) Data Sources (OleDB)(*.udl;*.*) ODBC DSN (Data Source Name)(*.dsn;*.*) OData (Open Data Protocol) v1/v2/v3/v4
- Resource.Net
سایر نرم افزارهای این تیم هم مانند نرم افزارهای معرفی شده بین کاربران محبوبیت زیادی کسب کرده اند که میتوانید برای کسب اطلاعات بیشتر و دانلود این نرم افزارها به وب سایت این تیم مراجعه فرمائید.
ASP.NET Core
- قسمت اول: Net Core. چیست؟
- قسمت دوم: بررسی ساختار جدید Solution
- قسمت سوم: Middleware چیست؟
- قسمت چهارم: فعالسازی پردازش فایلهای استاتیک
- قسمت پنجم: فعالسازی صفحات مخصوص توسعه دهنده ها
- قسمت ششم: سرویسها و تزریق وابستگی ها
- قسمت هفتم: کار با فایلهای Config
- قسمت هشتم: فعالسازی ASP.NET MVC
- قسمت نهم: بررسی تغییرات مسیریابی
- قسمت دهم: بررسی تغییرات Viewها
- قسمت یازدهم: بررسی بهبودهای Razor
- قسمت دوازدهم: معرفی Tag Helpers
- قسمت سیزدهم: معرفی View Components
- قسمت چهاردهم: فعال سازی اعتبارسنجی ورودیهای کاربران
- قسمت پانزدهم: بررسی تغییرات Caching
- قسمت شانزدهم:کار با Sessions
- قسمت هفدهم: بررسی فریم ورک Logging
- قسمت هجدهم: کار با ASP.NET Web API
- قسمت نوزدهم: بومی سازی
- قسمت بیستم: بررسی تغییرات فیلترها
- قسمت بیست و یکم: بررسی تغییرات Bundling و Minification
- قسمت بیست و دوم: توزیع برنامه توسط IIS
- پیاده سازی Unobtrusive Ajax در ASP.NET Core 1.0
- امکان استفادهی مستقیم از کتابخانههای Full .NET Framework در NET Core 2.0.
- Tag Helper Components در ASP.NET Core 2.0
- کار با Razor در ASP.NET Core 2.0
- فعالسازی Windows Authentication در برنامههای ASP.NET Core 2.0
ASP.NET Core Identity
- سفارشی سازی
- امکان ساخت قالب برای پروژههای NET Core.
- تبدیل قالبهای سفارشی پروژههای NET Core. به بستههای NuGet
- افزودن و اعتبارسنجی خودکار Anti-Forgery Tokens در برنامههای Angular مبتنی بر ASP.NET Core
- تولید هدرهای Content Security Policy توسط ASP.NET Core برای برنامههای Angular
- غیرمعتبر شدن کوکیهای برنامههای ASP.NET Core هاست شدهی در IIS پس از ریاستارت آن
- اعتبارسنجی مبتنی بر JWT در ASP.NET Core 2.0 بدون استفاده از سیستم Identity
- اعتبارسنجی مبتنی بر کوکیها در ASP.NET Core 2.0 بدون استفاده از سیستم Identity
- فعالسازی HSTS در ASP.NET Core
- مراحل تنظیم Let's Encrypt در IIS
- IdentityServer 4x
- قسمت اول - نیاز به تامین کنندهی هویت مرکزی
- قسمت دوم - ایجاد ساختار اولیهی مثال این سری
- قسمت سوم - بررسی مفاهیم OpenID Connect
- قسمت چهارم - نصب و راه اندازی IdentityServer
- قسمت پنجم - پیاده سازی ورود و خروج از سیستم
- قسمت ششم - کار با User Claims
- قسمت هفتم- امن سازی Web API
- قسمت هشتم- تعریف سطوح دسترسی پیچیده
- قسمت نهم- مدیریت طول عمر توکنها
- قسمت دهم- ذخیره سازی اطلاعات کاربران IDP در بانک اطلاعاتی
- قسمت یازدهم- استفاده از تامین کنندههای هویت خارجی
- قسمت دوازدهم- یکپارچه سازی با اکانت گوگل
- قسمت سیزدهم- فعالسازی اعتبارسنجی دو مرحلهای
- قسمت چهاردهم- آماده شدن برای انتشار برنامه
- قسمت اول - نیاز به تامین کنندهی هویت مرکزی
کار با Areas در ASP.NET Core
کار با کوکیها در ASP.NET Core
بررسی روش آپلود فایلها در ASP.NET Core
ارسال ایمیل در ASP.NET Core
نوشتن Middleware سفارشی در ASP.NET Core
نوشتن TagHelperهای سفارشی برای ASP.NET Core
بررسی تغییرات Reflection در NET Core.
استفادهی گسترده از DateTimeOffset در NET Core.
بررسی روش دسترسی به HttpContext در ASP.NET Core
توزیع پروژههای ASP.NET Core 1.1 بدون ارائه فایلهای View آن
تغییرات رمزنگاری اطلاعات در NET Core.
ساخت بستههای نیوگت مخصوص NET Core.
تهیه قالب برای ارسال ایمیلها در ASP.NET Core توسط Razor Viewها
روش یافتن لیست تمام کنترلرها و اکشن متدهای یک برنامهی ASP.NET Core
بررسی روش آپلود فایلها از طریق یک برنامهی Angular به یک برنامهی ASP.NET Core
سفارشی سازی صفحهی اول برنامههای Angular CLI توسط ASP.NET Core
تغییرات Encoding در NET Core.
پیاده سازی برنامههای چند مستاجری در ASP.NET Core
مقدمهای بر تزریق وابستگیها درASP.NET Core
نمایش خطاهای اعتبارسنجی سمت سرور ASP.NET Core در برنامههای Angular
احراز هویت و اعتبارسنجی کاربران در برنامههای Angular - قسمت اول - معرفی و ایجاد ساختار برنامه
روش استفادهی صحیح از HttpClient در برنامههای دات نت
اجرای سرویسهای NodeJS در ASP.NET Core
بررسی خطاهای ممکن در حین راه اندازی اولیه برنامههای ASP.NET Core در IIS
تست کردن متدهای یک Controller به کمک PowerShell
کار با Visual Studio در ASP.NET Core