مطالب
حذف لایه‌های جدید اضافه شده به فایل‌های PDF توسط iTextSharp
شاید یک سری از Ebookهای PDF ایی را دیده باشید که سایت‌های ثالث، آن‌ها را پس از افزودن لایه‌ای متنی، مثلا در ذیل تمام صفحات به همراه آدرس وب سایت خودشان، باز انتشار می‌دهند. در مطلب جاری قصد داریم، نحوه حذف این لایه‌های اضافی را توسط iTextSharp بررسی کنیم.




یافتن و حذف لایه‌های اضافه شده به صفحات یک فایل PDF

برای آشنایی با ساختار سطح پایین لایه‌های اضافه شده نیاز است به برنامه iText Rups مراجعه کنیم.


همانطور که مشاهده می‌کنید، برای رسیدن به لایه‌ای که حاوی متن اضافه شده به ذیل تمام صفحات است، نیاز است ابتدا صفحات را گشوده و سپس CONTENTS آن‌ها را استخراج کنیم. در این CONTENTS کلیه streamهای موجود را بررسی و هر کدام که حاوی متن مورد نظر ما بودند، یافته و سپس آن استریم را با مقدار دهی طول آن به صفر، حذف کنیم. روش کار را در متد ذیل مشاهده می‌کنید:
        private static void removeWatermarkLayer(string watermarkedFile, string text,  string unwatermarkedFile)
        {
            PdfReader.unethicalreading = true;
            PdfReader reader = new PdfReader(watermarkedFile);
            reader.RemoveUnusedObjects();
            int pageCount = reader.NumberOfPages;
            for (int i = 1; i <= pageCount; i++)
            {
                var page = reader.GetPageN(i);                
                var contentarray = page.GetAsArray(PdfName.CONTENTS);
                if (contentarray == null)
                    continue;

                for (int j = 0; j < contentarray.Size; j++)
                {
                    var stream = (PRStream)contentarray.GetAsStream(j);
                    //دریافت محتوای خام صفحه
                    var content = System.Text.Encoding.ASCII.GetString(PdfReader.GetStreamBytes(stream));
                    if (content.Contains(text))
                    {
                        //حذف کامل محتوا از فایل
                        stream.Put(PdfName.LENGTH, new PdfNumber(0));
                        stream.SetData(new byte[0]);
                    }
                }
            }

            using (var fileStream = new FileStream(unwatermarkedFile, FileMode.Create, FileAccess.Write, FileShare.None))
            {
                using (var stamper = new PdfStamper(reader, fileStream))
                {
                    stamper.SetFullCompression();
                    stamper.Close();
                }
            }
        }
در این متد watermarkedFile همان فایل اصلی دارای لایه‌های اضافی است. Text متنی است که در استریم‌های صفحات به دنبال آن خواهیم گشت و unwatermarkedFile نام و مسیر فایل تصحیح شده نهایی است که قرار است تولید شود.
نظرات مطالب
تعریف نوع جنریک به صورت متغیر
سلام آقای نصیری .
ممنون از مطلب مفیدتون. من این کد رو نوشتم برای اینکه یک کلاس رو به متد جنریک بفرستم ولی نمیدونم چطور میتونم T رو به کلاسی که میخوام Cast کنم. ممنون میشم من رو راهنمایی بفرمایید:

var clsType = typeof(MyClass);var method = typeof(TestGenerics).GetMethods().First(x => x.Name == "Print" && (x.GetParameters()[0]).ParameterType.IsGenericParameter);genericMethod = method.MakeGenericMethod(new[] { clsType });genericMethod.Invoke(null, new object[] { new MyClass{P1=100,P2="Name"} });Console.Read();var clsType = typeof(MyClass);var method = typeof(TestGenerics).GetMethods().First(x => x.Name == "Print" && (x.GetParameters()[0]).ParameterType.IsGenericParameter);genericMethod = method.MakeGenericMethod(new[] { clsType });genericMethod.Invoke(null, new object[] { new MyClass{P1=100,P2="Name"} });Console.Read();var method = typeof(TestGenerics).GetMethods().First(x => x.Name == "Print" && (x.GetParameters()[0]).ParameterType.IsGenericParameter);genericMethod = method.MakeGenericMethod(new[] { clsType });genericMethod.Invoke(null, new object[] { new MyClass{P1=100,P2="Name"} });Console.Read();new[] { clsType });genericMethod.Invoke(null, new object[] { new MyClass{P1=100,P2="Name"} });Console.Read();null, new object[] { new MyClass{P1=100,P2="Name"} });Console.Read();Console.Read();و  public static void Print(T data) { if (typeof(T) == typeof(MyClass)){var cls = (MyClass)data;}} که از خط آخر ایراد میگیره static void Print(T data) { if (typeof(T) == typeof(MyClass)){var cls = (MyClass)data;}} که از خط آخر ایراد میگیرهif (typeof(T) == typeof(MyClass)){var cls = (MyClass)data;}} که از خط آخر ایراد میگیرهvar cls = (MyClass)data;}} که از خط آخر ایراد میگیره
نظرات اشتراک‌ها
معرفی کتابخانه‌ی DNTCaptcha.Core
- بسته‌ی coreCompat.Drawing برای NETStandard 1.3. کامپایل شده‌است. یعنی با NET 4.5.1. سازگار است (چون دات نت 4.5.1 هم استاندارد 1.3 را پیاده سازی می‌کند).
+ آیا منظور شما استفاده از برنامه‌های ASP.NET Core ایی است که از Full .NET Framework استفاده می‌کنند؟ یا منظور ASP.NET MVC 5.x است؟
اگر مورد اول مدنظر است، بله، می‌توان با کمی تغییر در نحوه‌ی کامپایل آن، بسته‌ی نیوگت مخصوص آن‌را تولید کرد که از coreCompat.Drawing استفاده نکند و از این لحاظ مشکلی نیست. ولی اگر مورد دوم مدنظر شما است، coreCompat.Drawing فقط یکی از موارد استفاده شده‌است. برای مثال قسمت رمزنگاری آن از IDataProtector استفاده می‌کند که مختص NET Core. است و معادلی در MVC 5.x ندارد و یا نحوه‌ی نمایش آن توسط یک Tag Helper سفارشی ASP.NET Core است.
در کل برای MVC 5.x از مواردی مانند « نحوه ایجاد یک تصویر امنیتی (Captcha) با حروف فارسی در ASP.Net MVC » استفاده کنید.
نظرات مطالب
مدیریت سراسری خطاها در یک برنامه‌ی Angular
- در مورد اینکه چه استثناهایی باید مدیریت شوند یا خیر، مطلب «نکات کار با استثناءها در دات نت» را مطالعه کنید.
- علت عمل نکردن فیلتری که به آن لینک دادید (که من با آن موافق نیستم)، این است که دیگر نباید از میان‌افزار مدیریت استثناهای مخصوص توسعه دهنده‌های ASP.NET Core در این حالت استفاده کنید، چون با آن تداخل می‌کند و پیش از آن وارد عمل می‌شود. علت دریافت صفحه‌ی HTML ایی که مشاهده می‌کنید، همین مورد است. این صفحه برای برنامه‌های ASP.NET Core دارای Viewهای Razor طراحی شده‌است و نه مخصوص حالت کار صرفا Web API آن.
- یکی از مشکلات آن فیلتر هم این است که به هیچ عنوان نباید اصل خطای رخ‌داده‌ی در سمت سرور را به سمت کلاینت ارسال کرد و به کاربر نمایش داد. این مورد امکان دیباگ از راه دور برنامه‌ی شما را توسط یک مهاجم سهولت می‌بخشد و از دیدگاه امنیتی اشتباه است. این موارد را فقط باید توسط امکانات Logging توکار ASP.NET Core ثبت و در سمت سرور با «دسترسی ادمین» بررسی کنید. کاربر هم فقط باید جمله‌ی کلی «خطایی رخ داده‌است» را مشاهده کند و نه جزئیات آن‌را.
مطالب
یک سرویس (میکروسرویس) چیست؟ و چگونه آن را مستند کنیم؟ (قسمت دوم)
در قسمت اول این مقاله ، مشخصات کلیدی یک سرویس مورد بررسی قرار گرفت و  API‌ها و وابستگی‌ها یا Dependencies هر سرویس نیز مورد بررسی قرار گرفتند. همانطور که مشخص است با زیاد شدن این سرویس‌ها و وابستگی هایی که به یکدیگر پیدا میکنند، سردرگمی‌ها نیز برای اعضای تیم‌های مختلف، زیاد میگردد. چرا که افراد هر تیم دائما باید از API‌های ارائه شده توسط تیم‌های دیگر مطلع باشند. به همین جهت زمانیکه شما یک سبک معماری مانند میکروسرویس را انتخاب می‌نمایید، باید یک روش مستند سازی مناسب را نیز انتخاب نمایید تا مانع از پیچیدگی و سردرگمی ناشی از نبود مستندات مناسب و سربار هماهنگی بین تیمی شوید.

در این مطلب، 2 روش زیر، جهت مستند سازی سرویس‌ها بررسی می‌شوند:
 روش اول - کارت طراحی میکروسرویس (microservice design card)
 روش دوم - بوم میکروسرویس ( microservice canvas)

لازم به ذکر است که دو روش فوق می‌توانند مکمل یکدیگر باشند؛ همچنین این اسناد (علاوه بر مفید بودن برای مصرف کنندگان سرویس) حتی جهت شناسایی سرویس‌ها و ارتباطات بین آنها در زمان تحلیل (در جلساتی مانند event storming) نیز می‌توانند کاربردی باشند.


روش اول - کارت طراحی میکروسرویس (microservice design card) 
روش کارت طراحی میکروسرویس بر اساس کارت‌های CRC که گاهی اوقات در Object-oriented design استفاده می‌شوند، مدل سازی شده‌است و می‌توان از آن جهت ثبت خدمات سرویس و همچنین تعاملات سرویس، با سایر سرویس ها، استفاده نمود (این اطلاعات نسبت به اطلاعات قابل درج در microservice canvas که در ادامه بررسی می‌شود، کمتر است).
می‌توانید این کارت‌ها را در ابعاد کوچک و به تعداد کافی پرینت و در هنگام تحلیل و طراحی سرویس(ها)، از آنها استفاده نمایید
در نهایت جهت کشیدن نقشه وابستگی سرویس‌ها، کارت‌ها روی یک برد نصب و با کشیدن خطوط بین سرویس‌ها، وابستگی‌های هر یک را مشخص نمایید. مزیت اصلی این روش در طراحی، همکاری بیشتر تیم‌ها با یکدیگر می‌باشد.

(نمونه ای از کارت طراحی ‌های مربوط سرویس‌های project و archive)



روش دوم  - بوم میکروسرویس (microservice canvas)
یکی دیگر از روش‌های مناسب برای مستند سازی یک سرویس و ساختار درونی آن، استفاده از روش بوم میکروسرویس می‌باشد. بوم میکروسرویس نیز تا حدودی شبیه به کارت‌های CRC و همچنین روش microservice design card که پیش‌تر بررسی گردید، می‌باشد؛ با این تفاوت که اطلاعات بیشتری را نگهداری می‌نماید.
روش طراحی روی بوم جهت مستند سازی، از گذشته در صنایع مختلفی از جمله صنعت نرم افزار رایج بوده است؛ ولی ظاهرا برای اولین بار در سال 2017 و در این مقاله  (از سایت DZone که توسط Matt McLarty و Irakli Nadareishvili منتشر شده‌است) از این روش به عنوان روشی برای مستند سازی سرویس‌ها (در معماری میکروسرویس) استفاده شده‌است . پس از آن و در طول زمان، نمونه‌های مختلف و نسبتا مشابهی از این بوم توسط افراد و شرکت‌های مختلف ارائه شد (که با جستجوی عبارت microservice canvas در بخش تصاویر سایت گوگل می‌توانید نمونه‌های متفاوت آن را بررسی نمایید). در ادامه این مقاله، بوم میکروسرویسی که آقای ریچاردسون در سال 2019 معرفی نمودند، بررسی می‌گردد.

تصویر فوق بوم مربوط به سرویس Order می‌باشد

با توجه به تصویر فوق و مفاهیم بررسی شده در قسمت قبلی این مقاله، به بررسی بخش‌های مختلف بوم میکروسرویس می‌پردازیم.

نمای بیرونی یک سرویس (A service’s external view) در بوم میکروسرویس توسط بخش‌های زیر معرفی می‌گردد
• Name – نام سرویس
• Description – ارائه یک توضیح مختصر در مورد سرویس
• Capabilities – معرفی بخش‌هایی از منطق کسب و کار که در این سرویس پیاده سازی شده‌است.
• Service APIs – معرفی عملیات یا operations (شامل commands  و queries) که در این سرویس پیاده سازی شده‌اند و همچنین معرفی وقایع یا همان domain event هایی که توسط سرویس منتشر می‌شوند.
• Quality attributes – معرفی non-functional requirements‌های سرویس
• Observability (قابلیت‌های مشاهده و بررسی  سرویس) – معرفی health check endpoints و key metrics و ... .

وابستگی‌های یک سرویس (A service’s dependencies)  که لزوما استفاده بیرونی ندارد و بیشتر منبعی برای خود اعضای تیم خواهد بود، در بخشی تحت عنوان dependencies مشخص می‌شوند که خود شامل دو قسمت به شرح زیر می‌باشد: 
• Invokes – عملیاتی که در سایر سرویس‌ها پیاده سازی شده‌اند و در این سرویس فراخوانی می‌گردند.
• Subscribes – اشتراک در کانال پیام‌هایی که شامل وقایع سایر سرویس‌ها می‌باشند.

موارد مربوط به پیاده سازی یک سرویس (A service’s implementation)
در بوم میکروسرویس علاوه بر تمام موارد فوق، شما میتوانید مدل پیاده سازی لایه دامنه را نیز معرفی نمایید. همچنین نام bounded context‌ها و aggregateهای پیاده سازی شده در این سرویس، در این بخش نوشته می‌شود (که در یک حالت ایده آل، تنها یک agg از یک bc در یک سرویس پیاده سازی خواهد شد).

تولید بوم میکروسرویس 
با توجه به دغدغه ناشی از به روز نگه داشتن بوم میکروسرویس (و به طور کلی مستندات پروژه) همراه با تغییرات پروژه، تکنیک‌ها و ابزارهایی جهت تولید خودکار فایل json بوم میکروسرویس (microservice-canvas-tools) و همچنین جهت به تصویر کشیدن فایل json تولید شده (microservices-design-canvas-editor ) وجود دارد. اما اگر ابزار مناسبی را با توجه به پلتفرم مورد نظر، نتواستید پیدا کنید و یا فرصت توسعه یک ابزار اختصاصی نبود، همواره می‌توان این فایل را به صورت دستی نیز ایجاد نمود و در مخزن کد مربوط به پروژه و در کنار سورس اصلی نگه داری کرد تا همراه با سایر مستندات پروژه، این سند نیز پس از هر تغییر به روز شود. نسخه‌ای از آن را نیز می‌توان در محلی مناسب با سایر تیم‌ها به اشتراک گذاشت.

در صورتیکه قصد تولید و توسعه دستی این سند را دارید، نسخه‌ای از آن را در قالب فایل ورد، می‌توانید در این مخزن در گیت هاب پیدا نمایید.
مطالب
مثال ساده پرداخت بانکی با استفاده از تراکنش و پروسیجر در مای اس‌ کیو ال
برای انجام عملیاتی مثل عملیات حسابداری، نیاز به انجام پی در پی چندین دستور می‌باشد و در صورت انجام نشدن یکی از آنها، بقیه نیز نامعتبر خواهند بود که برای پیاده سازی این مکانیزم از تراکنش‌ها در بانک اطلاعاتی استفاده می‌شود. تراکنش‌ها معمولآ در بدنه‌ی توابع ذخیره شده روی بانک (stored procedure) پیاده سازی می‌شوند. برای تعریف یک پروسیجر در مای اس کیو ال من از برنامه‌ی MySQL Workbench  به شکل زیر استفاده می‌کنم. البته می‌توان دستور ایجاد تابع را از روش‌های دیگر هم اجرا کرد.


در مای اس کیو ال برای تعریف یک تابع از ساختار زیر استفاده می‌کنیم :
DELIMITER $$

CREATE 
          DEFINER=`user_name`@`host_name`|CURRENT_USER 
          PROCEDURE `transition_name`(

IN | OUT  | INOUT `parameter_name` type(bigint,int , ...)
)
    SQL SECURITY  DEFINER| INVOKER
transition_name: BEGIN

#----procedure_body 

END
نکات مربوط به تعریف :
در قسمت
  DEFINER=`user_name`@`host_name`|CURRENT_USER
کسی که تابع را تعریف کرده معرفی می‌شود. اگر شما برای انتقال دیتابیس از جایی به جای دیگر، از روش ایمپورت و اکسپورت استفاده کنید، اگر نام کاربری بانک شما متفاوت باشد، معمولآ این قسمت باعث خطا می‌شود؛ چون شما نمی‌توانید به نام فرد دیگری تابع بسازید. پیش فرض هم مقدار
CURRENT_USER
در نظر گرفته می‌شود که همان اسم کاربری و هاست شما است.
نکته بعدی : قسمت
SQL SECURITY  DEFINER| INVOKER
است که استفاده کننده از پروسیجر را مشخص می‌کند. مقدار DEFINER یعنی فقط تعریف کننده حق استفاده از این پروسیجر را دارد و مقدار INVOKER یعنی هر کسی حق استفاده از این تابع را دارد .
برای شرح تراکنش، مثال پرداخت بانکی را شرح می‌دهیم:
DELIMITER $$

CREATE 
        DEFINER=CURRENT_USER
        PROCEDURE `transition_pay`(
                #-----------input value
               IN `pay_value` bigint,
               IN `admin_id` int,
               #-------------result code 
               OUT `result` bigint
)
    SQL SECURITY INVOKER
transition_pay: BEGIN 
DECLARE  admin_credit DOUBLE  DEFAULT  0;   
SELECT `Credit`
INTO   admin_credit  
FROM  `Admin`

WHERE `Admin_id` = admin_id 
#----- transaction  body
END
در قسمت بالا متغیری را تعریف کرده و آخرین میزان اعتبار ادمین را داخل آن قرار دادیم تا در قسمت تراکنش، مقدار پرداختی را به آن اضافه کنیم و دو باره ادمین را آپدیت کنیم.
 اگر بخواهیم به دلیلی قبل از رسیدن به تراکنش آن را کنسل کنیم، می‌توان از دستور LEAVE استفاده کرد:
 مثال :
IF admin_id=0 THEN 
set result = -1 ; 
#exit procedure
LEAVE transition_pay;
END IF;
حال شروع تراکنش حالت ساده  :
START TRANSACTION;
          INSERT INTO 
                                 `PayBalance` (`Value` , `Admin_id` )
                                  VALUES (pay_value,  admin_id);

          UPDATE `Admin`
           SET `Credit`=admin_credit + pay_value  
          WHERE `admin_id`=admin_id;
COMMIT;
با پایان تراکنش، تمام مقادیر به درستی در بانک ذخیره می‌گردند.
حال اگر بخواهیم به دلیلی داخل تراکنش آن را لغو کنیم از دستور ROLLBACK استفاده می‌کنیم. 
مثال:
IF pay_value=0 THEN 
set result = -1 ; 
#roolback procedure
ROLLBACK ;
END IF;  
برای اطمینان از اجرا شدن دستورات در مای اس کیو ال می‌توان از
SET autocommit = {0 | 1}
نیز استفاده کرد که مقدار پیش فرض آن یک است. یعنی هر دستوری بلافاصله اجرا شود. می‌توان قبل از دستوراتی که می‌خواهیم پی در پی اجرا شوند، یک بار آن را صفر و بعد از اجرای دستورات آنرا یک کنیم.
نکته آخر اینکه با استفاده ار زبان پی اچ پی هم می‌توان تراکنشی را شروع و تمام کرد و بین این دو دستورات مورد نظر را نوشت و همیشه وجود پروسیجر الزامی نیست.
مطالب
LocalDB FAQ
SQL Server Express LocalDB یا به صورت خلاصه LocalDB، یک بانک اطلاعاتی‌است که به صورت متصل به پروسه‌ی برنامه‌ی جاری اجرا می‌شود؛ برخلاف رویه‌ی متداول بانک‌های اطلاعاتی که به صورت یک سرویس مستقل اجرا می‌شوند. هدف آن، جایگزین کردن نگارش Express نیست و بیشتر حجم کم و سهولت توزیع آن مدنظر بوده‌است. برای مثال نگارش Express به صورت یک سرویس مجزا و مستقل بر روی سیستم نصب می‌شود؛ اما LocalDB به همراه و متصل به برنامه‌ی نوشته شده، اجرا می‌شود:


اگر به تصویر فوق دقت کنید، یک child process جدید به نام sqlservr.exe نیز به همراه برنامه‌ی آزمایشی ما به صورت خودکار اجرا شده‌است. این child process به همراه پارامترهای ذیل است (که توسط NET Framework. مقدار دهی می‌شوند و مدیریت نهایی آن خودکار است):
 "C:\Program Files\Microsoft SQL Server\120\LocalDB\Binn\\sqlservr.exe"   
-c -SMSSQL12E.LOCALDB
-sLOCALDB#5657074F
-d"C:\Users\Vahid\AppData\Local\Microsoft\Microsoft SQL Server Local DB\Instances\MSSQLLocalDB\master.mdf"
-l"C:\Users\Vahid\AppData\Local\Microsoft\Microsoft SQL Server Local DB\Instances\MSSQLLocalDB\mastlog.ldf"
-e"C:\Users\Vahid\AppData\Local\Microsoft\Microsoft SQL Server Local DB\Instances\MSSQLLocalDB\error.log"
بنابراین LocalDB برخلاف SQL Server CE، یک بانک اطلاعاتی in-process نیست و به صورت یک پروسه‌ی مجزا اجرا می‌شود. زمانیکه از SQL Server CE استفاده می‌شود، موتور این بانک اطلاعاتی چند فایل DLL بیشتر نیستند و نهایتا اجرای آن داخل پروسه‌ی برنامه‌ی ما و همانند اجرای سایر DLLهای متصل و مورد استفاده‌ی به آن است.
اما LocalDB یک بانک اطلاعاتی user-mode است و در پروفایل کاربر جاری سیستم اجرا می‌شود. این بانک اطلاعاتی یک بار بر روی سیستم نصب می‌شود و در هر برنامه‌ای که از آن استفاده می‌کنید، یک child process مجزای خاص خودش را (sqlservr.exe) اجرا خواهد کرد. اجرا و خاتمه‌ی این child processها نیز خودکار هستند و نیازی به دخالت مستقیم برنامه ندارند.
البته به نظر توسعه‌ی SQL Server CE متوقف شده‌است و دیگر پشتیبانی نمی‌شود. بنابراین گزینه‌ی ترجیح داده شده‌ی برای کارهایی با حجم‌های بانک اطلاعاتی زیر 10 گیگابایت ، می‌تواند LocalDB باشد. به علاوه اینکه قابلیت‌های T-SQL بیشتری را نیز پشتیبانی می‌کند و همچنین پشتیبانی منظمی نیز از آن وجود دارد. برای مثال پیش نمایش نگارش 2016 آن نیز موجود است.

در ادامه، یک سری پرسش و پاسخ متداول جهت کار با LocalDB را مرور خواهیم کرد.


محل دریافت آخرین نگارش مستقل آن کجاست؟

همانطور که عنوان شد، یکی از مهم‌ترین اهداف LocalDB، سهولت توزیع آن است و عدم نیاز به یک Admin سیستم، برای نصب و نگهداری آن. نگارش 2014 SP1 آن‌را از آدرس ذیل می‌توانید دریافت کنید:
https://www.microsoft.com/en-us/download/details.aspx?id=46697

در اینجا نسخه‌های متعددی وجود دارند. برای مثال اگر سیستم شما 64 بیتی است، تنها نیاز است ENU\x64\SqlLocalDB.msi را دریافت و نصب کنید:



پارامترهای نصب خاموش آن برای توزیع ساده‌ی برنامه کدامند؟

اگر می‌خواهید نصاب LocalDB را به همراه setup برنامه‌ی خود توزیع کنید، می‌توانید روش توزیع خاموش را با ذکر پارامترهای ذیل، مورد استفاده قرار دهید:
 msiexec /i SqlLocalDB.msi /qn IACCEPTSQLLOCALDBLICENSETERMS=YES


رشته‌ی اتصالی مخصوص آن کدام است؟

  <connectionStrings>
    <add name="Sample35Context"
        connectionString="Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\test.mdf;Integrated Security=True;"
        providerName="System.Data.SqlClient" />
  </connectionStrings>
اگر نگارش 2014 SP1 آن‌را نصب کرده باشید، رشته‌ی اتصالی فوق، تمام آن‌چیزی است که برای شروع به کار با آن، نیاز دارید و دارای دو قسمت مهم است:
الف) ذکر وهله‌ی مدنظر
در اینجا وهله‌ی MSSQLLocalDB ذکر شده‌است؛ اما چه وهله‌هایی بر روی سیستم نصب هستند و چطور می‌توان وهله‌ی دیگری را ایجاد کرد؟ برای این منظور، به پارامترهای sqlservr.exe ابتدای بحث دقت کنید. اکثر آن‌ها به پوشه‌ی ذیل اشاره می‌کنند:
 C:\Users\your_user_name_here\AppData\Local\Microsoft\Microsoft SQL Server Local DB\Instances
با یک چنین محتوایی

در این پوشه، وهله‌‌های موجود و نصب شده‌ی بر روی سیستم شما نمایش داده می‌شوند که یکی از آن‌ها را می‌توانید در رشته‌ی اتصالی فوق ذکر کنید.
به علاوه، این لیست را توسط برنامه‌ی کمکی SqlLocalDB.exe، به همراه پارامتر info یا i نیز می‌توانید دریافت و بررسی کنید:


برنامه‌ی کمکی SqlLocalDB.exe به همراه نصاب LocalDB، نصب می‌شود و توسط آن می‌توان نگارش‌های مختلف نصب شده‌را با پارامتر v و وهله‌ی مختلف موجود را با پارامتر i مشاهده کرد.
همچنین اگر می‌خواهید وهله‌ی جدیدی را بجز وهله‌ی پیش فرض MSSQLLocalDB ایجاد کنید، می‌توانید از پارامتر create آن به نحو ذیل استفاده نمائید:
For LocalDB SQL EXPRESS 2014
 "C:\Program Files\Microsoft SQL Server\120\Tools\Binn\SqlLocalDB.exe" create "v12.0" 12.0 -s

For LocalDB SQL Express 2012
 "C:\Program Files\Microsoft SQL Server\110\Tools\Binn\SqlLocalDB.exe" create "v11.0" 11.0 -s

ب) ذکر DataDirectory
در رشته‌ی اتصالی فوق، پارامتر DataDirectory نیز ذکر شده‌است تا بتوان مسیر بانک اطلاعاتی را به صورت نسبی و بدون ذکر عبارت دقیق آن که ممکن است در سیستم‌های دیگر متفاوت باشد، پردازش کرد. این پارامتر در برنامه‌های وب به پوشه‌ی استاندارد app_data اشاره می‌کند و نیازی به تنظیم اضافه‌تری ندارد. اما در برنامه‌های دسکتاپ باید به نحو ذیل به صورت دستی، در آغاز برنامه مقدار دهی شود:
 AppDomain.CurrentDomain.SetData("DataDirectory", AppDomain.CurrentDomain.BaseDirectory);
به این ترتیب DataDirectory به محل قرارگیری فایل exe برنامه اشاره می‌کند. بدیهی است در اینجا هر پوشه‌ی دیگری را نیز می‌توانید ذکر کنید:
 AppDomain.CurrentDomain.SetData("DataDirectory", Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "db"));
برای نمونه تنظیم فوق به زیر پوشه‌ی db، در کنار فایل exe برنامه اشاره می‌کند.


محل نصب بانک‌های اطلاعاتی پیش فرض آن کدام است؟

ذکر AttachDbFilename در رشته‌ی اتصالی فوق، اختیاری است. در صورت عدم ذکر آن، بانک اطلاعاتی ایجاد شده را در یکی از مسیرهای ذیل می‌توانید جستجو کنید:
 C:\Users\USERNAME\AppData\Local\Microsoft\Microsoft SQL Server Local DB\Instances
C:\Users\USERNAME\AppData\Local\Microsoft\VisualStudio\SSDT
همچنین در این محل‌ها فایل‌های log متنی خطاهای این بانک اطلاعاتی را نیز می‌توان مشاهده کرد. بنابراین اگر به خطای خاصی برخوردید، بهترین کار، بررسی این فایل‌‌ها است.


آیا می‌توان فایل‌های mdf و ldf آن‌را به نگارش کامل SQL Server متصل (attach) کرد؟

بله. اما باید دقت داشته باشید که SQL Server به محض اتصال یک بانک اطلاعاتی با نگارش پایین‌تر به آن، ابتدا شماره نگارش آن‌‌را به روز می‌کند. یعنی دیگر نخواهید توانست این بانک اطلاعاتی را با نگارش پایین‌تر LocalDB باز کنید و یک چنین پیام خطایی را دریافت خواهید کرد:
 The database xyz cannot be opened because it is version 706. This server supports version 663 and earlier. A downgrade path is not supported.


چگونه محتوای بانک‌های اطلاعاتی LocalDB را با VS.NET مشاهده کنیم؟

از منوی view گزینه‌ی server explorer را انتخاب کنید. بر روی data connections کلیک راست کرده و گزینه‌ی Add connection را انتخاب کنید.


در صفحه‌ی باز شده، گزینه‌ی Microsoft SQL server  را انتخاب کنید. در صفحه‌ی بعد، ذکر server name مطابق data source رشته‌ی اتصالی بحث شده و سپس انتخاب گزینه‌ی attach a database file کفایت می‌کند:


پس از کلیک بر روی ok، امکان کار با اجزای این بانک اطلاعاتی را خواهید داشت:



چگونه از LocalDB با EF استفاده کنیم؟

EF 6.x به صورت پیش فرض از بانک اطلاعاتی LocalDB استفاده می‌کند و تنها داشتن یک چنین تنظیمی در فایل کانفیگ برنامه، برای کار با آن کافی است:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <connectionStrings>
    <add name="Sample35Context"
        connectionString="Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\test.mdf;Integrated Security=True;"
        providerName="System.Data.SqlClient" />
  </connectionStrings>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="mssqllocaldb" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
</configuration>
یک قسمت آن ذکر رشته‌ی اتصالی است که در مورد آن بحث شد و قسمت دوم آن، ذکر connection factory مخصوص localdb است که به صورت فوق می‌باشد. تنظیم دیگری برای کار با LocalDB و EF 6.x نیازی نیست.
البته باید دقت داشت که اسمبلی EntityFramework.SqlServer نیز به صورت خودکار به همراه بسته‌ی نیوگت EF 6.x به برنامه اضافه می‌شود که استفاده‌ی از connection factory ذکر شده را میسر می‌کند.


استفاده‌ی از LocalDB به همراه برنامه‌های وب چگونه است؟

سه نکته را باید در حین استفاده‌ی از LocalDB، در برنامه‌های وب اجرا شده‌ی بر روی IIS مدنظر داشت:
الف) LocalDB یک بانک اطلاعاتی user-mode است و child process آن تحت مجوز اکانت تنظیم شده‌ی برای آن کار می‌کند.
ب) همانطور که عنوان شد، در رشته‌ی اتصالی ذکر شده، پارامتر DataDirectory به پوشه‌ی استاندارد app_data اشاره می‌کند که فایل‌های قرار گرفته‌ی در آن توسط IIS محافظت می‌شوند و از طریق وب قابل دسترسی و دانلود نیستند.
ج) child process مربوط به LocalDB، نیاز به دسترسی write، برای کار با فایل‌های mdf و ldf خود دارد.

برای مورد الف نیاز است تا به تنظیمات application pool برنامه مراجعه کرده و سپس بر روی آن کلیک راست کرد و گزینه‌ی advanced settings را انتخاب نمود. در اینجا گزینه‌ی load user profile باید true باشد:


تنظیم load user profile ضروری است اما کافی نیست. پس از آن باید setProfileEnvironment را نیز به true تنظیم کرد. تنظیم این مورد در کنسول مدیریتی IIS به صورت زیر است.
ابتدا ریشه‌ی اصلی سرور را انتخاب کنید و سپس به configuration editor آن وارد شوید:


در ادامه از دارپ داون آن، گزینه‌ی system.applicationHost و زیر شاخه‌ی applicationPools آن‌را انتخاب کنید:


در اینجا application pool defaults و سپس در آن processModel را نیز باز کنید:


اکنون امکان ویرایش setProfileEnvironment را به true خواهید داشت:


پس از این تنظیم، ابتدا بر روی دکمه‌ی apply سمت راست صفحه کلیک کرده و سپس نیاز است یکبار IIS را نیز ریست کنید تا تنظیمات اعمال شوند.


در ادامه برای تنظیم دسترسی write (موارد ب و ج)، ابتدا بر روی پوشه‌ی app_data برنامه، کلیک راست کرده و برگه‌ی security آن‌را باز کنید. سپس بر روی دکمه‌ی edit کلیک کرده و در صفحه‌ی باز شده بر روی دکمه‌ی add کلیک کنید تا بتوان به کاربر application pool برنامه دسترسی write داد:


در اینجا iis apppool\TestLocalDB را وارد کرده و بر روی دکمه‌ی check name کلیک کنید.

iis apppool آن که مشخص است. عبارت TestLocalDB نام application pool ایی است که برای برنامه‌ی وب خود ایجاد کرده‌ایم (بهتر است به ازای هر برنامه‌ی وب، یک application pool مجزا تعریف شود).


در اینجا بر روی OK کلیک کرده و به این کاربر جدید اضافه شده، دسترسی full control را بدهید تا برنامه و یوزر آن بتواند فایل‌های mdf و ldf را ایجاد کرده و به روز رسانی کنند.

پس از تنظیم load user profile و همچنین set profile environment و دادن دسترسی write به کاربر application pool برنامه، اکنون child process مربوط به local db را می‌توان ذیل پروسه‌ی IIS مشاهده کرد و برنامه قادر به استفاده‌ی از LocalDB خواهد بود:

مطالب
نحوه نمایش منوهای Visual studio 2012 با حروف کوچک
چند روز پیش بصورت اتفاقی به این فکر افتادم که چرا منوهای visual studio 2012 برخلاف ظاهر زیبای خود محیط، اینقدر زمخت و با حروف بزرگ نوشته است.


و اینکه به چه صورت میتوانم آنها را بصورت حروف کوچک نمایش دهم و حس کنجکاوی اونم از نوع مخصوص گل کرد.


برای اینکار دو روش وجود دارد :
روش 1 - تغییر مقدار در رجیستری سیستم عامل ویندوز
 بدین صورت که شما باید به این مسیر مراجعه نموده
در ویندوز 7 :
  HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\11.0\General\
در ویندوز 8 :
 HKEY_CURRENT_USER\Software\Microsoft\VSWinExpress\11.0\General\
در نسخه web express:
 HKEY_CURRENT_USER\Software\Microsoft\VSWDExpress\11.0\General\

ایجاد یک کلید از نوع DWORD :


و با نام SuppressUppercaseConversion و با مقدار 1 در مسیر یاد شده تنظیم نمائید.

 
سپس راه اندازی مجدد visual studio  و مشاهده منوهای تغییر یافته .

روش 2 - کسانی مثل من کمی تنبل هستند و از این کارهای فوق دوست ندارند راه آسانتر را میتوانند تجربه کنند بصورت ذیل:
 
 در منوی start ویندوز با تایپ کلمه powershell  و انتخاب Windows PowerShell به صفحه‌ای آبی رنگ (در ویندوز 7 ) وارد میشود .


 دستور ذیل را کپی و به پنجره powershell انتقال دهید :
Set-ItemProperty -Path HKCU:\Software\Microsoft\VisualStudio\11.0\General -Name SuppressUppercas
eConversion -Type DWord -Value 1

  سپس راه اندازی مجدد visual studio  و مشاهده منوهای تغییر یافته   
مطالب
چگونه برنامه‌های دات نت را خارج از ویژوال استودیو دیباگ کنیم؟
مشکل: نگارش  1.0.808.0 برنامه‌ی DNTProfiler بر روی سایر سیستم‌ها، هنوز به مرحله‌ی نمایش نرسیده، کرش می‌کند. علت چیست؟

این نگارش بر روی سیستم من مشکلی نداشت ولی پس از چند گزارش عدم امکان اجرای آن بر روی سایر سیستم‌ها، یک ماشین مجازی ویندوز 8.1 را تهیه و برنامه را بر روی آن اجرا کردم. بله ... برنامه هنوز به مرحله‌ی نمایش نرسیده، محو می‌شد. در این مرحله‌ی ابتدایی امکان تهیه‌ی لاگ استثنای حاصل توسط برنامه وجود نداشت و تنها این خطا در event viewer ویندوز (Computer management -> event viewer -> windows logs -> application) قابل مشاهده بود:
 Application: DNTProfiler.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.Windows.Markup.XamlParseException
Stack:
at System.Windows.Markup.WpfXamlLoader.Load
متاسفانه از این استثنای لاگ شده‌ی در لاگ‌های ویندوز، اطلاعات مفیدی را نمی‌توان دریافت کرد. عنوان کرده XamlParse برنامه را نمی‌تواند آغاز کند.
روش حل این نوع مشکلات و بررسی آن‌ها در خارج از VS.NET، با استفاده از برنامه‌ی معروف WinDBG مایکروسافت میسر است.
دو نگارش 32 بیتی و 64 بیتی آن‌را از اینجا می‌توانید دریافت کنید:
http://codemachine.com/downloads.html

پس از دریافت، بهتر است نسخه‌ی 32 بیتی آن‌را اجرا کنید، زیرا برای دیباگ برنامه‌های دات نت این نسخه است که امکان بارگذاری فایل C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll را دارد.

تا اینجا فرض بر این است که نسخه‌ی 32 بیتی windbg را دریافت و اجرا کرده‌اید. در ادامه از منوی File آن گزینه‌ی Open executable را انتخاب کرده و فایل exe برنامه را به آن معرفی کنید.
 CommandLine: C:\Tests\DNTProfiler.1.0.808.0\DNTProfiler.exe
Symbol search path is: srv*
Executable search path is:
ModLoad: 00150000 00176000 DNTProfiler.exe
ModLoad: 76f30000 77098000 ntdll.dll
ModLoad: 72ee0000 72f36000 C:\Windows\SysWOW64\MSCOREE.DLL
ModLoad: 74be0000 74d20000 C:\Windows\SysWOW64\KERNEL32.dll
ModLoad: 756e0000 757af000 C:\Windows\SysWOW64\KERNELBASE.dll
(684.764): Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=00000000 ecx=37af0000 edx=00000000 esi=7eb8f000 edi=00000000
eip=76fe2d15 esp=002ff604 ebp=002ff630 iopl=0 nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b efl=00000246
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for ntdll.dll -
ntdll!LdrResolveDelayLoadsFromDll+0xa89:
76fe2d15 cc   int   3
برنامه داخل این دیباگر اجرا شده و در همینجا نیز به پایان می‌رسد. در ادامه‌ی کار در textbox ذیل این گزارش، دستور g را صادر کرده و enter کنید.
 0:000> g
ModLoad: 757b0000 75827000 C:\Windows\SysWOW64\ADVAPI32.dll
ModLoad: 05080000 05102000 Newtonsoft.Json.dll
(684.764): C++ EH exception - code e06d7363 (first chance)
(684.764): C++ EH exception - code e06d7363 (first chance)
(684.764): C++ EH exception - code e06d7363 (first chance)
(684.764): CLR exception - code e0434352 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=002fd0a0 ebx=00000005 ecx=00000005 edx=00000000 esi=002fd164 edi=00000001
eip=756f3d67 esp=002fd0a0 ebp=002fd0f8 iopl=0 nv up ei pl nz ac pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b efl=00200216
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\SysWOW64\KERNELBASE.dll -
KERNELBASE!RaiseException+0x48:
756f3d67 8b4c2454   mov   ecx,dword ptr [esp+54h] ss:002b:002fd0f4=3fce1188
فرمان g سبب می‌شود تا کار دیباگ برنامه ادامه پیدا کند و به اولین CLR exception رسیده و متوقف شود. در ادامه نیاز است تا با صدور فرمان sxe clr، دیباگ clr را فعال کرده و سپس مجددا دستور g را برای ادامه‌ی دیباگ صادر کنیم.
 0:000> sxe clr
0:000> g
(684.764): C++ EH exception - code e06d7363 (first chance)
(684.764): CLR exception - code e0434352 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=002fe2a0 ebx=00000005 ecx=00000005 edx=00000000 esi=002fe368 edi=00000001
eip=756f3d67 esp=002fe2a0 ebp=002fe2fc iopl=0 nv up ei pl nz ac pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b efl=00200216
KERNELBASE!RaiseException+0x48:
756f3d67 8b4c2454   mov   ecx,dword ptr [esp+54h] ss:002b:002fe2f4=3fce2388
بنابراین ابتدا دستور sxe clr را صادر و enter و سپس g و enter. مجددا برنامه پس از رسیدن به یک CLR exception متوقف می‌شود.
اکنون می‌خواهیم پیام استثنای واقعی دات نت را مشاهده کنیم. به همین جهت ابتدا دستور loadby sos clr! و سپس دستور CLRStack! را صادر می‌کنیم:
 0:000> !loadby sos clr
0:000> !CLRStack
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll -
PDB symbol for clr.dll not loaded
OS Thread Id: 0x764 (0)
Child SP IP Call Site
002fe3f4 756f3d67 [GCFrame: 002fe3f4]
002fe430 756f3d67 [GCFrame: 002fe430]
002fe528 756f3d67 [GCFrame: 002fe528]
002fe544 756f3d67 [HelperMethodFrame_2OBJ: 002fe544] System.RuntimeTypeHandle.CreateInstance(System.RuntimeType, Boolean, Boolean, Boolean ByRef, System.RuntimeMethodHandleInternal ByRef, Boolean ByRef)
DNTProfiler.App.Main()
002ff190 720e2652 [GCFrame: 002ff190]
در اینجا کار بررسی stack trace برنامه پایان می‌یابد. اکنون با صدور دستور PrintException! می‌توان علت اصلی استثناء را مشاهده کرد:
 0:000> !PrintException
Exception object: 021e6f0c
Exception type: System.Reflection.TargetInvocationException
Message: Exception has been thrown by the target of an invocation.
InnerException: System.IO.FileNotFoundException, Use !PrintException 021e6950 to see more.
StackTrace (generated):
<none>
StackTraceString: <none>
HResult: 80131604
0:000> !PrintException 021e6950
Exception object: 021e6950
Exception type: System.IO.FileNotFoundException
Message: Could not load file or assembly 'System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.
InnerException: <none>
StackTrace (generated):
SP IP Function
00000000 00000001 DNTProfiler!DNTProfiler.Services.SelfHostConfig.getHostConfiguration(System.String, Boolean)+0x2
002FE298 006B4E54 DNTProfiler!DNTProfiler.Services.SelfHostConfig.OpenWait(System.String, Boolean)+0x14
002FE2B0 006B4A3F DNTProfiler!DNTProfiler.ViewModels.MainWindowViewModel.doStart(System.String)+0x1f
002FE2C0 006B368D DNTProfiler!DNTProfiler.ViewModels.MainWindowViewModel..ctor(DNTProfiler.Common.Mvvm.ICommonDialogsService, DNTProfiler.Common.Controls.DialogManagement.Contracts.IDialogManager)+0xcd
002FE2D8 006B04C9 DNTProfiler!DNTProfiler.MainWindow..ctor()+0x91

StackTraceString: <none>
HResult: 80070002
همانطور که مشاهده می‌کنید، عنوان کرده‌است که فایل System.Net.Http.Formatting قابل بارگذاری نیست. بله ... این فایل جزو بسته‌ی نگارش اول برنامه نبود و به نظر علت عدم کرش آن، نصب این فایل در GAC سیستم توسط نصاب‌های ASP.NET MVC بوده‌است (نگارش‌های 3 و 4 آن). بنابراین اگر کسی این فایل را در GAC سیستم خود نداشته باشد، قادر به اجرای برنامه نخواهد بود.
روش حل این مشکل، مراجعه به خواص پروژه، یافتن اسمبلی System.Net.Http.Formatting در لیست ارجاعات برنامه و سپس true کردن خاصیت copy to local آن است. به این ترتیب این اسمبلی در کنار فایل اجرایی برنامه کپی خواهد شد.

بنابراین خلاصه‌ی عملیات یافتن علت اصلی کرش برنامه در خارج از ویژوال استودیو به صورت ذیل است:
الف) اجرای نسخه‌ی 32 بیتی برنامه‌ی windbg
ب) انتخاب منوی File آن و سپس باز کردن فایل اجرایی برنامه توسط گزینه‌ی Open executable
ج) اجرای دستورات ذیل به ترتیب:
 0:000> g
0:000> sxe clr
0:000> g
0:000> !loadby sos clr
0:000> !CLRStack
0:000> !PrintException

چند نمونه‌ی مشابه برای مطالعه‌ی بیشتر
Finding CLR exceptions without visual studio
Power of WinDBG: The story of mysterious crash of WPF application
نظرات مطالب
PersianDatePicker یک DatePicker شمسی به زبان JavaScript که از تاریخ سرور استفاده می‌کند
سلام 
 تاریخی که برگشت داده میشه همراه با زمان است اما مقدار زمان صفر در نظر گرفته میشه و  صفر هم در کنار تاریخ برای زمان ذخیره میشه ، سوالی که پیش میاد اینه که  همزمان با تاریخ دریافتی ، زمان را هم میشه دریافت کرد؟(منظورم در همون فیلدی که برای تاریخ در نظر  گرفته شده نه به صورت جدا) 
با تشکر