نظرات مطالب
اعمال تزریق وابستگی‌ها به مثال رسمی ASP.NET Identity
با تشکر از توجه شما. 
در این پروژه نمونه و با همین تنظیمات، شرایط بدین گونه است: 
کاربر سایت را به صورت ناشناس مشاهده می‌کند. سپس با اطلاعات خود وارد سایت می‌شود. پس از تعییت هویت، مثلا به بخش Product هم دسترسی پیدا می‌کند. تا این مرحله همه چیز خوب است و خیر. سپس از حساب خود خارج می‌شود و دقایقی بعد، مجددا وارد حساب خود می‌شود. از این لحظه به بعد، رفتار برنامه متفاوت می‌شود. چرا که با وجود اینکه کاربر تایید هویت شده، اما اگر بخواهد مثلا دوباره به همان بخش Product مراجعه کند، سیستم ابتدا او را به صفحه‌ی ورود هدایت کرده و با کاربر، به عنوان یک کاربر ناشناخته برخورد می‌کند. همین گونه است برای سایر قسمتهایی که صفت Authorize  برای آنها لحاظ شده. پرسش من این است که آیا این رفتار طبیعی ست؟
قبلا گفتم که با تغییر مقدار validateInterval   ظاهرا این مشکل بر طرف می‌شود. لااقل این رفتار تغییر می‌کند. شما  فرمودید که در نظرگرفتن هر عددی جز صفر، موجب می‌شود تا کوکی بلافاصله به روز نشود. این صحبت شما کاملا صحیح و منطقی. اما آیا ورودهای مکرر به نظر شما منطقی ست؟
به کدهای این پروژه هم دقت کردم. مقدار validateInterval   برابر با 30 لحاظ شده که ظاهرا نباید اینگونه باشد. برای اینکه هم به رویکردی که شما به آن اشاره کردید برسیم و هم کاربر مجبور نباشد مدام Login کند، لطفا بفرمایید که چه تغییراتی لازم است؟ در صورتیکه من اشتباه کرده ام و یا چیزی را ندیده و یا از قلم انداخته ام، لطف می‌کنید اگر راهنمایی بفرمایید.
نظرات مطالب
یکسان سازی ی و ک دریافتی حین استفاده از NHibernate
سلام و عرض ادب
اگر کلیت مشکل فارسی و عربی را بررسی کنیم به گمانم به 3 سطح زیر میرسیم
1- تبدیل در ویندوز
2- تبدیل در UI
3- تبدیل در بانک اطلاعاتی

در تایید فرمایش شما ، شخصا چون صدها کاربر با میلیونها رکورد پراکند در سطح کشور دارم که همگی از هر دو ویندوز XP و 7 میخواهند استفاده کنند و هزینه تبدیل اطلاعات قبلی به فارسی بسیار بالاست ، ترجیح میدهم ادامه ورود اطلاعاتم روی عربی باشد .

اما در سطح بانک اطلاعاتی بدلیل کنترلهای فراوان و احتمال خطا زیاد موافق نیستم (اگر نیاز است میتوانم توضیح بیشتری بدهم )

در سطح UI هم همانگونه که فرمودید مشکلات عدیده ایی وجود دارد

در سطح ویندوز بهترین راه حل است ..اما نمیدانم چگونه میتوانم انرا پیاده کنم . اگر بتوانید راهنمایی بفرمایید من در مورد پیاده سازی و یا سرمایه گذاری روی پیاده سازی مشکلی ندارم

مرسی

وکیلی

Javan_Soft@Yahoo.com
مطالب
آشنایی با FileTable در SQL Server 2012 بخش 2
ستون دیگر stream_id نام دارد که از نوع uniqueidentifier ROWGUIDCOL است. همان‌گونه که در یاد دارید، در FileStream نیز ناگزیر به تعریف چنین ستونی بودیم. بنابراین FileTable استثناء نیست و در این‌جا نیست چنین فیلدی توسط SQL Server تعریف می‌شود. اگر فایل‌ها و پوشه‌ها جابه‌جا نمی‌شدند می‌توانستید از هر دو ستون path_locator یا stream_id برای شناسایی یک رکورد از جدول بهره ببرید. ولی با جابه‌جایی یک فایل و یا به عبارت دیگر تغییر پدر آن در ساختار سلسله‌مراتبی، مقدار path_locator نیز تغییر می‌کند، پس ناگزیر به استفاده از این ستون برای ارجاع به یک ردیف در جدول هستیم.
هر ردیف از جدول نمایان‌گر یک فایل یا پوشه است، بنابراین به ستونی نیاز داریم که بتوانیم این موضوع را نشان دهیم. بر این پایه از ستون is_directory بهره می‌بریم که 1 بودن آن نشان‌دهنده‌ی این است که این ردیف از جدول به یک پوشه ارجاع دارد.
نام فایل یا پوشه در ستونی به نام name نگه‌داری می‌شود که رشته‌ای از نوع (nvarchar(255 است. افزون بر این ستون، ستون‌های دیگری نیز در این جدول وجود دارد که ویژگی‌های یک فایل مانند پنهان‏‌بودن، فقط‏‌خواندنی و ... توسط آن توسط آن به دست می‏آید. ستون پسین file_stream نام دارد که برای پوشه‌ها، محتوای آن Null است. علت آن این است که محتوای واقعی فایل در این ستون نگه‌داری می‌شود. در واقع یک (varbinary(max با ویژگی‌های fileStream است که محتوای باینری آن در سیستم فایل NTFS ذخیره می‌شود. مدیریت پشت صحنه‌ی این ستون برعهده‌ی SQL Server است.
افزون بر این 14 ستون، هر FileTable شامل سه ستون محاسباتی به شرح زیر است:

ستون parent_path_locator نتیجه‏‌ی فراخوانی تابع (GetAncestor(1 در ستون path_locator است که جهت به دست آوردن پوشه‏‌ی پدر یک فایل و پوشه استفاده می‏‌شود. ستون file_type که از مقدار رشته‏‌ای ستون name تجزیه شده است، پسوند فایل را برمی‏‌گرداند. و ستون cached_file_size اندازه‌ی بایت ذخیره‏‌شده ستون file_stream  را برمی‏‌گرداند. با این ساختار ثابت در اینجا، هر FileTable هر آن‏چه از File System نیاز دارید در یک پوشه‏ی اشتراکی به شما می‏‌دهد.

این یعنی نمایش بی‏‌واسطه FileTable به هر کاربر یا برنامه. به طوری که برای نمایش یا به‏‌روزرسانی جدول می‌توانید از روش استاندارد I/O مانند کشیدن و رهاکردن با Windows Explorer یا برنامه‏‌نویسی با  System.IO.FileStream  و API‌های ویندوز استفاده کنید. این‏‌چنین:

- ایجاد یک فایل یا پوشه در سیستم فایل  -> افزودن یک ردیف به جدول

- افزودن یک ردیف به جدول -> ایجاد یک فایل یا پوشه در سیستم فایل 

با کپی فایل‌ها در مسیر بالا، به صورت خودکار رکوردهای زیر در جدول PhotoTable در پایگاه‌داده‌ها افزوده می‌شود: 

به طور خلاصه پیش از این برای افزودن به FileStream دو راه کار پیش رو داشتید. یکی استفاده از T-SQL و دیگر sqlFileStream اکنون SQL Server 2012 راه کار سوم را پیشنهاد می‌کند. استفاده از File System در این روش FileStream  به طور خودکار پر می‌شود. 

پیش از ساخت یک FileTable بیان این نکته دارای اهمیت است که با کپی فایل‏‌ها و پوشه‏‌ها هیچ چیز جدیدی به NTFS افزوده نمی‌شود بلکه محتوای فایل به FileStream افزوده می‌شود و SQL Server با بررسی همزمان FileStream و FileTable نمایشی از ردیف‏‌های FileTable به صورت یک پوشه‏‌ی اشتراکی نشان می‌دهد. این نکته پاسخی به این پرسش خواهد بود که آیا با استفاده از FileTable حجم پایگاه‏‌داده‏‌ها دو برابر خواهد شد و در نتیجه دشواری‏‌ها و چالش‏‌های نگه‏داری و پشتیبانی را پیش رو خواهیم داشت!؟ که پاسخ "خیر" خواهد بود. 

ایجاد یک  FileTable

پیش از این در همین تارنما، روش فعال کردن FileStream در SQL Server  را آموزش دیده اید. اگر درست به خاطر داشته باشید، چیزی شبیه به دستورهای زیر بود:

CREATE DATABASE MyFileArchive
ON PRIMARY
(NAME = MyFileArchive_data,
FILENAME = 'C:\Demo\MyFileArchive_data.mdf'),
FILEGROUP FileStreamGroup CONTAINS FILESTREAM
(NAME = PhotoFileLibrary_blobs,
FILENAME = 'C:\Demo\MyFiles')
LOG ON
(NAME = PhotoFileLibrary_log,
FILENAME = 'C:\Demo\MyFileArchive_log.ldf')

FileTable  به FileStream متکی است؛ بر این پایه پیش از ایجاد یک FileTable باید FileStream را روی پایگاه‌داده‌ها فعال کنیم. این کار با یک تعریف درست توسط بند FILEGROUP…CONTAINS FILESTREAM انجام می‌شود. 

برای ایجاد FileTable تنها کافی است که بند WITH FILESTREAM را به دستور CREATE DATABASE بیفزایید. (یا برای فعال‌کردن FileTable روی یک پایگاه‌داده‌ی ساخته شده بند SET FILESTREAM را در دستور ALTER DATABASE  بنویسید.) در این بند، از DIRECTORY_NAME برای نام‌گذاری یک پوشه برای پایگاه‌داده‌ها استفاده می‌کنیم. این پوشه در یک پوشه ریشه به نام SQL Server instance نمایش داده خواهد شد. بخش دوم بند NON_TRANSACTED_ACCESS=FULL  است که دسترسی غیرتراکنشی را فعال می‌کند.  با این کار برای هر FileTable  در پایگاه داده یک زیرپوشه درون پوشه‌ای که به نام DIRECTORY_NAME  نام‌گذاری شده است؛ ساخته می‌شود. 

با توجه به آنچه گفته شد برای ایجاد یک پایگاه‌داده با امکان ساخت FileTable دستورهای زیر را اجرا کنید: 

CREATE DATABASE MyFileArchive
ON PRIMARY
(NAME = MyFileArchive_data,
FILENAME = 'C:\Demo\MyFileArchive_data.mdf'),
FILEGROUP FileStreamGroup CONTAINS FILESTREAM
(NAME = PhotoFileLibrary_blobs,
FILENAME = 'C:\Demo\MyFiles')
LOG ON
(NAME = PhotoFileLibrary_log,
FILENAME = 'C:\Demo\MyFileArchive_log.ldf')
WITH FILESTREAM
(DIRECTORY_NAME='FilesLibrary',
NON_TRANSACTED_ACCESS=FULL)
اکنون برای ساخت یک FileTable درون این پایگاه‌داده‌ها از دستور زیر استفاده کنید:
USE MyFileArchive
GO
CREATE TABLE PhotoTable AS FileTable
GO
توجه داشته باشید که چون ستون‌های FileTable از پیش تعریف شده است؛ ایجاد آن فقط با نوشتن دستور امکان پذیر است و مانند یک Table عادی از محیط کاربری SQL Server نمی‌توان بهره برد. 
در Object Explorer از گره‏‌ی Tables، گره‏‌ی FileTables را باز کنید و روی جدولی که هم‌‏اکنون ساختیم راست‏‌کلیک کنید. با انتخاب گزینه‏‌ی Explore FileTable Directory پنجره‏‌ی زیر بازمی‏‌شود:

دنباله دارد ...

نظرات مطالب
فارسی کردن گرید تلریک در برنامه های ویندوزی
باسلام ببخشید من در گزارش میخوام ستون‌های گزارش دیتا گرید تلریک از راست به چپ باشه ولی تلریک پیش فرض از چپ به راست است ستون‌ها را قرار میدهد.از شما خواهش میکنم راه حل  این مشکل را در سایت قرار دهید.ضمنا از فارسی کردن دیتا گرید خیلی حال کردم.باتشکر
نظرات مطالب
EF Code First #4
سلام؛ من این مقاله رو خوندم و این پروژه رو تو MVC5 و vs2013 update1و EF6 انجام دادم. همه چی درسته ولی کلاس InitialCreate  رو ایجاد نمیکنه. آیا باید این کلاس رو دستی ایجاد کنم؟ من مدل‌ها و context رو تو اسمبلی‌های جدا گانه گذاشتم. در ضمن وقتی میخوام Enable-migrations رو انجام بدم اگه تو DataLayer به اسمبلی Web ارجاعی نداشته باشم، میگه Connectionstring درست نیست ولی کلاس مربوط به migration رو میسازه. ممنون میشم راهنمایی کنید. چون در نهایت باید در اسمبلی web به DataLayer ارجاعی داشته باشیم دیگه.
بازخوردهای دوره
طراحی روابط و ارجاعات در RavenDB
با سلام.
یک سوال در خصوص طراحی روابط  یک بلاگ دارم:
فرض کنید میخواهیم بخش تایم لاین را به برنامه اضافه کنیم بدین شرح: هر کاربری بتواند مشترک بلاگ‌های مورد علاقه اش شود و هر بار که به صفحه اول برنامه مراجعه میکند جدیدترین پست‌های بلاگ هایی که مشترک آنها بوده ببیند.
شاید یک نوع طراحی اینگونه باشد که جدولی داشته باشیم به نام «اشتراک» که در آن فیلد «نام کاربری نویسنده و نام کاربری مشترک» مورد نظر درج شود. سپس یک جدول هم داشته باشیم مثلاً به نام Timeline با فیلدهای «نام کاربری نویسنده، نام کاربری گیرنده، متن کامل مطلب و تاریخ ارسال».
هر زمان مطلب جدیدی منتشر شد، به ازای هر مشترک در جدول اشتراک، یک رکورد در جدول Timeline درج شود، در این حالت کار خواندن مطالب جدیدی که باید به کاربر نشان دهیم ساده میشود اما اگر یک کاربر مثلاً 10000 تا مشترک داشته باشد پس به ازای هر مطلب جدیدی که مینویسد باید 10000 رکورد در جدول Timeline درج شود، و اگر 100 نفر بخواهند مطلب بنویسند فکر کنم سیستم از کار بی افتد.
ممکن است من را راهنمایی کنید.  
ویرایش:
در این لینک صفحه 26   مطلب زیر رو هم پیدا کرم.

مطالب
WebStorage
webstorage تقریبا فناوری جدیدی است که برای نگهداری ثابت داده‌ها بر روی سیستم کاربر استفاده می‌شود. webstorage مزایای زیادی برای برنامه‌های تحت وب دارد. برای مثال با استفاده از آن میتوان فعالیت‌های کاربر را رصد کرد، بدون اینکه کد و دیتابیس سمت سرور را دخالت دهیم. حتی اگر سیستم کاربر آفلاین هم بشود برنامه می‌تواند همچنان به فعالیتش ادامه دهد. در این مقاله به مزایای این روش می‌پردازیم.

WebStorage در برابر کوکی ها
یکی از روش‌های سنتی ذخیره اطلاعات در سیستم کاربر، کوکی‌ها در بستر Http هستند. تفاوت‌های زیادی بین این دو وجود دارد که تعدادی از آن‌ها را در زیر بررسی می‌کنیم:

  • مکانیزم ذخیره سازی:
کوکی‌ها داده‌های ساخت یافته‌ای هستند که از وب سرور به سمت مرورگر کاربر به عنوان پاسخی در ازای درخواستی ارسال می‌شوند. درخواست و پاسخ کوکی‌ها شامل بخش هدر بوده که اطلاعات آن باعث شناسایی کوکی برای مدیریت و شناسایی آن‌ها می‌گردد تا هر موقع درخواستی صورت بگیرد، به سمت سرور برگشت خواهد خورد.
به طور خلاصه اینکه کوکی‌ها توسط درخواست‌ها و پاسخ‌ها ایجاد یا به روز می‌شوند. در نتیجه داده‌ها چه تغییر کرده باشند چه تغییر نکرده باشند، همیشه بخشی از هدر Http هستند. در سوی دیگر webstorage به طور کامل به صورت کلاینتی پیاده سازی گشته است و وب سرور را درگیر کار خودشان نمی‌کنند و کارایی بهتری را ارائه می‌دهند. از آنجا که همه چیز در خود سیستم کاربر اتفاق می‌افتد، در صورت از دست دادن کانکشن شبکه، کاربر می‌تواند همچنان به فعالیت‌های به روزرسانی و تغییر ادامه دهد.

  • چند نسخه از مرورگر
کاربری که با وب سایت مدنظر کار میکند میتواند توسط چند مرورگر مختلف یا چند تب و پنجره مختلف به طور همزمان کار کند و اطلاعات آن در همه‌ی مرورگرها و دیگر پنجره‌های آن مرورگر قابل دسترس می‌باشد.

  • محدودیت حجمی
محدودیت کوکی‌ها و webstorage از نظر حجم ذخیره سازی بین مروگرهای مختلف، متفاوت است. ولی در حالت کلی در بیشتر مرورگرها محدودیت حجم 4 کیلوبایت برای کوکی‌ها موجود است. (این ابزار می تواند نهایت حجمی را که که مرورگر شما از کوکی پشتیبانی می‌کند، نشان دهد.)
در مورد webstorage استاندارد W3C محدودیتی اعلام نکرده است و تصمیم گیری بر سر این موضوع را به سازندگان مرورگرها واگذار کرده است. ولی در حالت کلی حجم بیشتری از کوکی را ذخیره میکند و عموما تا 5 مگابایت توانایی ذخیره سازی وجود دارد. بدین ترتیب حجم آن 124,527% بیشتر از کوکی‌ها است. (این ابزار می‌تواند نهایت حجمی را که مرورگر شما از webstorage پشتیبانی می‌کند، ببینید).

انواع Webstorage 
دو نوع متد ذخیره سازی در webstorage داریم:
  • session storage
  • local storage

  • SessionStorage
داده‌هایی که بدین صورت ذخیره می‌شوند تنها تا زمانی دوام آورده و پایدار هستند که session مرورگر فعال است؛ یعنی تا زمانیکه کاربر در سایت فعلی حضور دارد.
استفاده از این روش برای ذخیره سازی‌های موقت عالی است. برای نمونه مقادیر ورودی فرمی که کاربر در حال کار با آن است، میتواند به طور موقت ذخیره شوند تا زمانی که کاربر بتواند تمامی مراحل را طی کرده، بدون اینکه ارجاعی به دیتابیس سمت سرور داشته باشد. همچنین ذخیره موقت داده‌ها می‌تواند به کاربر کمک کند تا در صورت reresh‌های ناگهانی یا بسته شدن‌های ناگهانی مرورگرها، نیازی به ورود مجدد داده‌ها نداشته باشد.
  • LocalStorage
در این روش داده‌ها با از دست رفتن session مرورگر جاری از بین نمی‌رود و برای بازدیدهای آتی کاربر از سایت، داده‌ها همچنان در دسترس هستند.
پشتیبانی مرورگرها
وب سایت caniuse گزارش می‌دهد که اکثر مرورگرها پشتیبانی خوبی از webstorage دارند.

با اینکه توصیه نامه W3C از پایان کار پیاده سازی این قابلیت خبر میدهد ولی در حال حاضر که این مقاله تدوین شده است هنوز نهایی اعلام نشده است. برای پشتیبانی مرورگرهای قدیمی از webstorage می‌توان از فایل جاوااسکریپتی Store.js کمک گرفت.


مفاهیم امنیتی و محافظت از داده ها

محدودیت‌های حمایتی و حفاظتی webstorage دقیقا همانند کوکی هاست. به این معنی که وب سایت‌های دیگر توانایی اتصال به webstorage سایت دیگری را ندارند. البته این مورد ممکن است برای وب سایت هایی که بر ساب دومین تکیه کرده‌اند ایجاد مشکل کند. برای حل این مسائل می‌توانید از کتابخانه‌های سورس بازی چون Cross Storage که توسط Zendesk ارائه شده است، استفاده کرد.

همانند هر مکانیزم ذخیره سازی سمت کلاینت، مواردی توصیه میگردد که رعایت آن‌ها از لحاظ امنیتی پر اهمیت است. به عنوان نمونه ذخیره‌ی اطلاعات شخصی و موارد حساس توصیه نمی‌گردد؛ چرا که احتمال دسترسی آسان نفوذگران به داده‌های محلی و خواندن آن‌ها وجود دارد.

Data Integrity یا یکپارچگی داده‌ها نیز در نظر گرفته شده است. باید حفاظتی در برابر عدم موفقیت ذخیره سازی داده‌ها نیز وجود داشته باشد. این عدم موفقیت‌ها میتواند به دلایل زیر رخ دهد:

  • اگر کاربر قابلیت webstorage را غیرفعال کرده باشد.
  • اگر فضایی برای کاربر باقی نمانده باشد.
  • با محدودیت حجمی webstorage مواجه شده است.
  • با مواجه شدن با خطاها یک استثنا صادر می‌شود که می‌توانید آن را دریافت و کنترلی را روی برنامه تحت وب داشته باشید. یک نمونه استثنا  QuotaExceededError  


IndexedDB

یکی از فرایندهای ذخیره سازی داده‌ها که همان مزایای webstorage را ارائه میدهد indexed Database API است. این قابلیت از HTML 5 اضافه شده است و قسمتی از مشخصات webstorage شناخته نمی‌شود. برای همین مستنداتی در حوزه‌ی webstorage برای آن پیدا نخواهید کرد ولی قابلیت‌هایی فراتر از webstorage  دارد.

این قابلیت پیچیدگی بیشتری را نسبت به خود webstorage ایجاد می‌کند، ولی فرصت‌های بسیاری را برای ذخیره سازی داده‌هایی با معماری‌های پیچیده‌تر و رابطه‌ها را می‌دهد. با استفاده از IndexedDB داده‌ها به شکل دیتابیس‌های سمت سرور RDMS ذخیره می‌شوند و این قابلیت را دارید که به سمت آن کوئری هایی مشابه بانک‌های اطلاعاتی سمت سرور را ارسال کنید.

در قسمت آتی نحوه کدنویسی آن را فرا خواهیم گرفت.

مطالب
نحوه استفاده صحیح از لوسین در ASP.NET
بر مبنای پیاده سازی متداولی که در n هزار سایت اینترنتی می‌توان یافت، نحوه کار با جستجوگر لوسین حدودا به این شکل است:
var directory = FSDirectory.Open(new DirectoryInfo(Environment.CurrentDirectory + "\\LuceneIndex"));
using (var searcher = new IndexSearcher(directory, readOnly: true))
{
      //do something ...

       searcher.Close();
       directory.Close();
}
و ... اینکار به این شکل غلط است!
مطابق مستندات رسمی لوسین، این کتابخانه thread-safe است. به این معنا که در آن واحد چندین و چند کاربر می‌توانند از یک وهله از شیء‌های Reader و Searcher استفاده کنند و نباید به ازای هر جستجو، یکبار این اشیاء را ایجاد و تخریب کرد. البته در اینجا تنها یک Writer در آن واحد می‌تواند مشغول به کار باشد.
مشکلاتی که به همراه باز و بسته کردن بیش از حد IndexSearcher وجود دارد، مصرف بالای حافظه است (به ازای هر کاربر مراجعه کننده، یکبار باید ایندکس‌ها در حافظه بارگذاری شوند) و همچنین تاخیر اولیه این بارگذاری و کندی آن‌‌را نیز باید مدنظر داشت.

نتیجه گیری:
برای کار با جستجوگر لوسین نیاز است از الگوی Singleton استفاده شود و تنها یک وهله از این اشیاء بین تردهای مختلف به اشتراک گذاشته شود.
 
مطالب
EF Code First #15

EF Code first و بانک‌های اطلاعاتی متفاوت

در آخرین قسمت از سری EF Code first بد نیست نحوه استفاده از بانک‌های اطلاعاتی دیگری را بجز SQL Server نیز بررسی کنیم. در اینجا کلاس‌های مدل و کدهای مورد استفاده نیز همانند قسمت 14 است و تنها به ذکر تفاوت‌ها و نکات مرتبط اکتفاء خواهد شد.


حالت کلی پشتیبانی از بانک‌های اطلاعاتی مختلف توسط EF Code first

EF Code first با کلیه پروایدرهای تهیه شده برای ADO.NET 3.5 که پشتیبانی از EF را لحاظ کرده باشند،‌ به خوبی کار می‌کند. پروایدرهای مخصوص ADO.NET 4.0، تنها سه گزینه DeleteDatabase/CreateDatabase/DatabaseExists را نسبت به نگارش قبلی بیشتر دارند و EF Code first ویژگی‌های بیشتری را طلب نمی‌کند.
بنابراین اگر حین استفاده از پروایدر ADO.NET مخصوص بانک اطلاعاتی خاصی با پیغام «CreateDatabase is not supported by the provider» مواجه شدید، به این معنا است که این پروایدر برای دات نت 4 به روز نشده است. اما به این معنا نیست که با EF Code first کار نمی‌کند. فقط باید یک دیتابیس خالی از پیش تهیه شده را به برنامه معرفی کنید تا مباحث Database Migrations به خوبی کار کنند؛ یا اینکه کلا می‌توانید Database Migrations را خاموش کرده (متد Database.SetInitializer را با پارامتر نال فراخوانی کنید) و فیلدها و جداول را دستی ایجاد کنید.


استفاده از EF Code first با SQLite

برای استفاده از SQLite در دات نت ابتدا نیاز به پروایدر ADO.NET آن است: «مکان دریافت درایور‌های جدید SQLite مخصوص دات نت»
ضمن اینکه به نکته «استفاده از اسمبلی‌های دات نت 2 در یک پروژه دات نت 4» نیز باید دقت داشت.
و یکی از بهترین management studio هایی که برای آن تهیه شده: «SQLite Manager»
پس از دریافت پروایدر آن، ارجاعی را به اسمبلی System.Data.SQLite.dll به برنامه اضافه کنید.
سپس فایل کانفیگ برنامه را به نحو زیر تغییر دهید:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.3.1.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</configSections>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0"/>
</startup>

<connectionStrings>
<clear/>
<add name="Sample09Context"
connectionString="Data Source=CodeFirst.db"
providerName="System.Data.SQLite"/>
</connectionStrings>
</configuration>

همانطور که ملاحظه می‌کنید، تفاوت آن با قبل، تغییر connectionString و providerName است.
اکنون اگر همان برنامه قسمت قبل را اجرا کنیم به خطای زیر برخواهیم خورد:
«The given key was not present in the dictionary»
در این مورد هم توضیح داده شد. سه گزینه DeleteDatabase/CreateDatabase/DatabaseExists در پروایدر جاری SQLite برای دات نت وجود ندارد. به همین جهت نیاز است فایل «CodeFirst.db» ذکر شده در کانکشن استرینگ را ابتدا دستی درست کرد.
برای مثال از افزونه SQLite Manager استفاده کنید. ابتدا یک بانک اطلاعاتی خالی را درست کرده و سپس دستورات زیر را بر روی بانک اطلاعاتی اجرا کنید تا دو جدول خالی را ایجاد کند (در برگه Execute sql افزونه SQLite Manager):

CREATE TABLE [Payees](
[Id] [integer] PRIMARY KEY AUTOINCREMENT NOT NULL,
[Name] [text] NULL,
[CreatedOn] [datetime] NOT NULL,
[CreatedBy] [text] NULL,
[ModifiedOn] [datetime] NOT NULL,
[ModifiedBy] [text] NULL
);

CREATE TABLE [Bills](
[Id] [integer] PRIMARY KEY AUTOINCREMENT NOT NULL,
[Amount] [float](18, 2) NOT NULL,
[Description] [text] NULL,
[CreatedOn] [datetime] NOT NULL,
[CreatedBy] [text] NULL,
[ModifiedOn] [datetime] NOT NULL,
[ModifiedBy] [text] NULL,
[Payee_Id] [integer] NULL
);

سپس سطر زیر را نیز به ابتدای برنامه اضافه کنید:

Database.SetInitializer<Sample09Context>(null);

به این ترتیب database migrations خاموش می‌شود و اکنون برنامه بدون مشکل کار خواهد کرد.
فقط باید به یک سری نکات مانند نوع داده‌ها در بانک‌های اطلاعاتی مختلف دقت داشت. برای مثال integer در اینجا از نوع Int64 است؛ بنابراین در برنامه نیز باید به همین ترتیب تعریف شود تا نگاشت‌ها به درستی انجام شوند.

در کل تنها مشکل پروایدر فعلی SQLite عدم پشتیبانی از مباحث database migrations است. این مورد را خاموش کرده و تغییرات ساختار بانک اطلاعاتی را به صورت دستی به بانک اطلاعاتی اعمال کنید. بدون مشکل کار خواهد کرد.

البته اگر به دنبال پروایدری تجاری با پشتیبانی از آخرین نگارش EF Code first هستید، گزینه زیر نیز مهیا است:
http://devart.com/dotconnect/sqlite/
برای مثال اگر علاقمند به استفاده از حالت تشکیل بانک اطلاعاتی SQLite در حافظه هستید (با رشته اتصالی ویژه Data Source=:memory:;Version=3;New=True;)،‌ فعلا تنها گزینه مهیا استفاده از پروایدر تجاری فوق است؛ زیرا مبحث Database Migrations را به خوبی پشتیبانی می‌کند.



استفاده از EF Code first با SQL Server CE

قبلا در مورد «استفاده از SQL-CE به کمک NHibernate» مطلبی را در این سایت مطالعه کرده‌اید. سه مورد اول آن با EF Code first یکی است و تفاوتی نمی‌کند (یک سری بحث عمومی مشترک است). البته با یک تفاوت؛ در اینجا EF Code first قادر است یک بانک اطلاعاتی خالی SQL Server CE را به صورت خودکار ایجاد کند و نیازی نیست تا آن‌را دستی ایجاد کرد. مباحث database migrations و به روز رسانی خودکار ساختار بانک اطلاعاتی نیز در اینجا پشتیبانی می‌شود.
برای استفاده از آن ابتدا ارجاعی را به اسمبلی System.Data.SqlServerCe.dll قرار گرفته در مسیر Program Files\Microsoft SQL Server Compact Edition\v4.0\Desktop اضافه کنید.
سپس رشته اتصالی به بانک اطلاعاتی و providerName را به نحو زیر تغییر دهید:

<connectionStrings>
<clear/>
<add name="Sample09Context"
connectionString="Data Source=mydb.sdf;Password=1234;Encrypt Database=True"
providerName="System.Data.SqlServerCE.4.0"/>
</connectionStrings>


بدون نیاز به هیچگونه تغییری در کدهای برنامه، همین مقدار تغییر در تنظیمات ابتدایی برنامه برای کار با SQL Server CE کافی است.
ضمنا مشکلی هم با فیلد Identity در آخرین نگارش EF Code first وجود ندارد؛ برخلاف حالت database first آن که پیشتر این اجازه را نمی‌داد و خطای «Server-generated keys and server-generated values are not supported by SQL Server Compact» را ظاهر می‌کرد.



استفاده از EF Code first با MySQL

برای استفاده از EF Code first با MySQL (نگارش 5 به بعد البته) ابتدا نیاز است پروایدر مخصوص ADO.NET آن‌را دریافت کرد: (^)
که از EF نیز پشتیبانی می‌کند. پس از نصب آن، ارجاعی را به اسمبلی MySql.Data.dll قرار گرفته در مسیر Program Files\MySQL\MySQL Connector Net 6.5.4\Assemblies\v4.0 به پروژه اضافه نمائید.
سپس رشته اتصالی و providerName را به نحو زیر تغییر دهید:

<connectionStrings>
<clear/>
<add name="Sample09Context"
connectionString="Datasource=localhost; Database=testdb2; Uid=root; Pwd=123;"
providerName="MySql.Data.MySqlClient"/>
</connectionStrings>

<system.data>
<DbProviderFactories>
<remove invariant="MySql.Data.MySqlClient"/>
<add name="MySQL Data Provider"
invariant="MySql.Data.MySqlClient"
description=".Net Framework Data Provider for MySQL"
type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.5.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
</DbProviderFactories>
</system.data>

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

با این تغییرات پس از اجرای برنامه قسمت قبل، به خطای زیر برخواهیم خورد:
The given key was not present in the dictionary

توضیحات این مورد با قسمت SQLite یکی است؛ به عبارتی نیاز است بانک اطلاعاتی testdb را دستی درست کرد. همچنین جداول و فیلدها را نیز باید دستی ایجاد کرد و database migrations را نیز باید خاموش کرد (پارامتر Database.SetInitializer را به نال مقدار دهی کنید).
برای این منظور یک دیتابیس خالی را ایجاد کرده و سپس دو جدول زیر را به آن اضافه کنید:

CREATE TABLE IF NOT EXISTS `bills` (
`Id` int(11) NOT NULL AUTO_INCREMENT,
`Amount` float DEFAULT NULL,
`Description` varchar(400) CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL,
`CreatedOn` datetime NOT NULL,
`CreatedBy` varchar(400) CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL,
`ModifiedOn` datetime NOT NULL,
`ModifiedBy` varchar(400) CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL,
`Payee_Id` int(11) NOT NULL,
PRIMARY KEY (`Id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_persian_ci AUTO_INCREMENT=1 ;

CREATE TABLE IF NOT EXISTS `payees` (
`Id` int(11) NOT NULL AUTO_INCREMENT,
`Name` varchar(400) CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL,
`CreatedOn` datetime NOT NULL,
`CreatedBy` varchar(400) CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL,
`ModifiedOn` datetime NOT NULL,
`ModifiedBy` varchar(400) CHARACTER SET utf8 COLLATE utf8_persian_ci NOT NULL,
PRIMARY KEY (`Id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_persian_ci AUTO_INCREMENT=1 ;

پس از این تغییرات، برنامه بدون مشکل اجرا خواهد شد (ایجاد بانک اطلاعاتی خالی به همراه ایجاد ساختار جداول و خاموش کردن database migrations که توسط این پروایدر پشتیبانی نمی‌شود).

به علاوه پروایدر تجاری دیگری هم در سایت devart.com برای MySQL و EF Code first مهیا است که مباحث database migrations را به خوبی مدیریت می‌کند.


مشکل!
اگر به همین نحو برنامه را اجرا کنیم، فیلدهای یونیکد فارسی ثبت شده در MySQL با «??????? ?? ????» مقدار دهی خواهند شد و تنظیم CHARACTER SET utf8 COLLATE utf8_persian_ci نیز کافی نبوده است (این مورد با SQLite یا نگارش‌های مختلف SQL Server بدون مشکل کار می‌کند و نیاز به تنظیم اضافه‌تری ندارد):

ALTER TABLE `bills` DEFAULT CHARACTER SET utf8 COLLATE utf8_persian_ci

برای رفع این مشکل توصیه شده است که CharSet=UTF8 را به رشته اتصالی به بانک اطلاعاتی اضافه کنیم. اما در این حالت خطای زیر ظاهر می‌شود:
The provider did not return a ProviderManifestToken string
این مورد فقط به اشتباه بودن تعاریف رشته اتصالی بر می‌گردد؛‌ یا عدم پشتیبانی از تنظیم اضافه‌ای که در رشته اتصالی ذکر شده است.
مقدار صحیح آن دقیقا مساوی CHARSET=utf8 است (با همین نگارش و رعایت کوچکی و بزرگی حروف؛ مهم!):

<connectionStrings>
<clear/>
<add name="Sample09Context"
connectionString="Datasource=localhost; Database=testdb; Uid=root; Pwd=123;CHARSET=utf8"
providerName="MySql.Data.MySqlClient"/>
</connectionStrings>


به این ترتیب، مشکل ثبت عبارات یونیکد فارسی برطرف می‌شود (البته جدول هم بهتر است به DEFAULT CHARACTER SET utf8 COLLATE utf8_persian_ci تغییر پیدا کند؛ مطابق دستور Alter ایی که در بالا ذکر شد).

نظرات مطالب
استفاده از GitHub Actions برای Build و توزیع خودکار پروژه‌های NET Core.
یک نکته تکمیلی :
به هنگام تغییر فایل .yaml مربوط به github actions از روی local (و نه خود github) و push کردن آن به گیتهاب ممکن است به خطای زیر برخورد کنید.
refusing to allow an OAuth App to create or update workflow `.github/workflows/dotnetcore.yml` without `workflow` scope
این باگ قبلا اینجا گزارش شده است و راه حل آن نیز اینجا و اینجا ارائه شده است.
راه حل این است که Credential Manager ویندوز رفته و گزینه مربوط به "git:https://github.com" را حذف کنید. بدین ترتیب زمانی که دوباره دستور git push را اجرا میکنید از شما مجددا Crediential را درخواست میکند و بعد از آن می‌توانید بدون مشکل فایل .yaml را هل بدهید [ push کنید (-; ]