dotnet tool update -g dotnet-outdated dotnet outdated -u dotnet restore
انتقال Context و Migrations به یک اسمبلی دیگر
تا اینجا اگر مثال بررسی شده را دنبال کرده باشید، دو پوشهی Entities و Migrations را به همراه فایلهای موجودیتها، Context برنامه و Migrations آنها، در همان پروژهی اصلی برنامه، خواهید داشت:
در ادامه قصد داریم بانک اطلاعاتی آزمایشی برنامه را drop کرده، پوشهی Migrations را حذف و صرفا دو فایل ApplicationDbContextSeedData و DBInitialization آنرا نگه داریم.
کلاس Person را به اسمبلی جدید Entities و کلاس ApplicationDbContext را به اسمبلی جدید DataLayer منتقل میکنیم:
اسمبلی جدید Core1RtmEmptyTest.Entities از نوع NET Core Class Library. است و صرفا حاوی کلاسهای موجودیتهای برنامهاست.
اسمبلی جدید Core1RtmEmptyTest.DataLayer نیز از نوع NET Core Class Library. بوده و حاوی تعاریف Context برنامه، به همراه Migrations و تنظیمات آن خواهد بود.
تا اینجا با این نقل و انتقالات، نیاز است وابستگیهای DataLayer را اصلاح کنیم. بنابراین فایل project.json آنرا گشوده و به نحو ذیل تکمیل نمائید:
{ "version": "1.0.0-*", "dependencies": { "Core1RtmEmptyTest.Entities": "1.0.0-*", "Microsoft.EntityFrameworkCore": "1.0.0", "Microsoft.EntityFrameworkCore.SqlServer": "1.0.0", "Microsoft.Extensions.Configuration.Abstractions": "1.0.0", "NETStandard.Library": "1.6.0" }, "frameworks": { "netstandard1.6": { "imports": "dnxcore50" } } }
وابستگی Microsoft.Extensions.Configuration.Abstractions برای کار با IConfigurationRoot اضافه شدهاست (دسترسی به تنظیمات برنامه از طریق تزریق وابستگیها).
به علاوه اکنون به پروژهی وب اصلی مراجعه کرده و فایل project.json آنرا جهت افزودن ارجاعاتی به این دو اسمبلی جدید، ویرایش کنید:
{ "dependencies": { // same as before "Core1RtmEmptyTest.Entities": "1.0.0-*", "Core1RtmEmptyTest.DataLayer": "1.0.0-*" } }
فعال سازی Migrations و قرار دادن فایلهای آن در اسمبلی Core1RtmEmptyTest.DataLayer
در ادامه اگر مانند قسمت قبل بخواهیم مهاجرتها را اضافه کنیم، به خطای ذیل خواهیم رسید:
D:\Prog\1395\Core1RtmEmptyTest\src\Core1RtmEmptyTest>dotnet ef migrations add InitialDatabase Your target project 'Core1RtmEmptyTest' doesn't match your migrations assembly 'Core1RtmEmptyTest.DataLayer'. Either change your target project or change your migrations assembly.
D:\Prog\1395\Core1RtmEmptyTest\src\Core1RtmEmptyTest.DataLayer>dotnet ef migrations add InitialDatabase No executable found matching command "dotnet-ef"
{ // same as before "tools": { "Microsoft.EntityFrameworkCore.Tools": { "version": "1.0.0-preview2-final", "imports": [ "portable-net45+win8" ] } }, // same as before }
D:\Prog\1395\Core1RtmEmptyTest\src\Core1RtmEmptyTest.DataLayer>dotnet ef migrations add InitialDatabase Could not invoke this command on the startup project 'Core1RtmEmptyTest.DataLayer'. This preview of Entity Framework tools does not support commands on class library projects in ASP.NET Core and .NET Core applications.
D:\Prog\1395\Core1RtmEmptyTest\src\Core1RtmEmptyTest.DataLayer>dotnet ef --startup-project ../Core1RtmEmptyTest/ migrations add InitialDatabase Done. To undo this action, use 'dotnet ef migrations remove'
اعمال کلاسهای Migrations تولید شده به بانک اطلاعاتی
پس از تولید موفقیت آمیز فایلهای مهاجرت، برای اعمال آنها به بانک اطلاعاتی، اینبار نیز دستور را از همان پوشهی DataLayer با پارامتر پروژهی آغازین اجرا میکنیم:
D:\Prog\1395\Core1RtmEmptyTest\src\Core1RtmEmptyTest.DataLayer>dotnet ef --startup-project ../Core1RtmEmptyTest/ database update Applying migration '13950527070105_InitialDatabase'. Done.
بنابراین به صورت خلاصه
- ابتدا قسمت tools تنظیمات پروژهی data layer را برای فعال سازی دستورات خط فرمان EF ویرایش کنید.
- سپس از طریق خط فرمان به پوشهی data layer وارد شوید. اینبار باید دستورات EF را از ریشهی این پوشه، بجای پوشهی اصلی برنامه صادر کرد.
- در اینجا دستورات افزودن مهاجرتها و به روز رسانی بانک اطلاعاتی، همانند قبل هستند. فقط ذکر محل واقع شدن پوشهی آغازین برنامه توسط پارامتر startup-project الزامی است.
نوروز مبارک!
منم سال نو رو به شما تبریک میگم و امیدوارم سال خوبی داشته باشید.
ضمنا از این پست استفاده میکنم و از شما بخاطر حمایت های که سال گذشته از من (و البته دیگر دوستان) کردید تشکر میکنم.
روی گزینهی Next کلیک کنید و در پنجرهای که باز میشود در قسمت Address نشانی وبسایتی که در بخش پیشین تولید کردیم و ممکن است شما در IIS افزوده باشید؛ قرار دهید و روی دکمهی GO بفشارید تا سرویس در کادر پایین افزوده شود. سپس در قسمت Namespace نامی مناسب برای فراخوانی سرویس وارد کنید آنگاه دکمهی OK را بفشارید.
از پنجرهی بازشده روی دکمهی Finish کلیک کنید. پس از مکثی کوتاه سرویس به همراه دو موجودیت آن درون Data Sources دیده خواهد شد. از آنطرف در Solution Explorer نیز در پوشهی Service References سرویس تعریفشده ارجاع داده خواهد گرفت.
از Data Sources روی tblNews کلیک کنید سپس آنرا کشیده و به روی فرم رها کنید. خواهید دید که یک DataGridView شامل همهی ویژگیهای موجودیت tblNews و یک Binding Navigator که با موجودیت tblNews در پیوند است و یک منبع داده به نام tblNewsBindingSource به صورت خودکار در فرم افزوده خواهد شد.
چیدمان فرم، رنگها، اندازهها و فونت را آنگونه که میپسندید تنظیم کنید. سپس ستونهایی که به آنها نیازی ندارید حذف یا پنهان کرده و عنوان ستونهای مانده را ویرایش کنید. کلیدهای افزودن، حذف و ذخیره را روی Navigator ایجاد کنید و بقیهی کلیدها را اگر به آن نیازی ندارید حذف کنید. البته میتوانید بنا به سلیقهی کاریتان یک Panel برای اینکار اختصاص دهید. در اینجا یک فرم ساده در نظر گرفته شده است:
اکنون نوبت به کدنویسی است. سورس فرم را بازکنید و نخست سرویس را به این صورت در جای مناسب تعریف کنید:
MyNewsService.MyNewsServiceClient MyNews = new MyNewsService.MyNewsServiceClient();
یک تابع کوچک برای تبدیل تاریخ میلادی به شمسی بنویسید سپس رویداد Load فرم را به این صورت بنویسید:
string MiladiToShamsi(DateTime MyDate) { System.Globalization.PersianCalendar pers = new System.Globalization.PersianCalendar(); return string.Format("{0}/{1}/{2}", pers.GetYear(MyDate), pers.GetMonth(MyDate).ToString("D2"), pers.GetDayOfMonth(MyDate).ToString("D2")); } private void Form1_Load(object sender, EventArgs e) { tblNewsBindingSource.DataSource = MyNews.GetAllNews().Select(p => new {p.tblNewsId, p.tblCategory.CatName, p.Title, p.Description, RegDate= MiladiToShamsi( p.RegDate) }); }
پیش از اجرای پروژه از Solution Explorer روی نام راه حل راستکلیک کنید و گزینهی Properties را انتخاب کنید. در پنجرهی بازشده تنظیمات زیر را انجام دهید:
این کار باعث میشود که به طور همزمان پروژهی وبسایت و ویندوز اجرا شود. اکنون پروژه را اجرا کنید. اگر با پیغام خطا روبهرو شدید؛ تگ Connection String را از App.Config پروژه WCF Library به Web.Config پروژه وبسایت کپی کنید. در این صورت پروژه به راحتی اجرا خواهد شد.
در بخش پسین پیرامون افزودن، ویرایش و حذف و برخی توضیحات برای توسعهی کار خواهم نوشت.
UserDialogs.Init(this); // Before Forms.Init
containerBuilder.RegisterInstance(UserDialogs.Instance);
public IUserDialogs UserDialogs { get; set; } public async Task Login() { if (string.IsNullOrWhiteSpace(UserName) || string.IsNullOrWhiteSpace(Password)) await UserDialogs.AlertAsync(message: "Please provide UserName and Password!", title: ")-:", okText: "Ok!"); }
using (UserDialogs.Loading("Logging in...", maskType: MaskType.Black)) { // Login implementation ... await Task.Delay(TimeSpan.FromSeconds(3)); }
await NavigationService.NavigateAsync("/Login", animated: false);
await NavigationService.NavigateAsync("/Nav/HelloWorld");
3- ممکن است بخواهید هنگام رفتن از صفحهای به صفحه دیگر، پارامتر نیز ارسال کنید. اگر برای مثال صفحه اول لیست محصولات را نمایش میدهد و با زدن روی هر محصول قرار است به صفحهای برویم که جزئیات آن محصول را ببینیم، بهتر است Id آن محصول به صورت پارامتر به صفحه دوم ارسال شود. برای این کار داریم:
await NavigationService.NavigateAsync("ProductDetail", new NavigationParameters { { "productId", productId } });
حال سؤال این است که در صفحه جزئیات یک محصول، چگونه productId را بگیریم؟ فرض کنید دو صفحه ProductsList و ProductDetail را داریم. هر صفحه دارای View و View Model است. در ViewModel مربوط به ProductDetail، یعنی ProductDetailViewModel که از BitViewModelBase ارث بری کردهاست، میتوانیم متد OnNavigatedToAsync را override کنیم. در آنجا به پارامترهای ارسال شده دسترسی داریم:
public async override Task OnNavigatedToAsync(INavigationParameters parameters) { await base.OnNavigatedToAsync(parameters); Guid productId = parameters.GetValue<Guid>("productId"); }
هر ViewModel علاوه بر OnNavigatedTo می تواند دارای OnNavigatedFrom هم باشد که زمانیکه داریم از صفحه مربوطه خارج میشویم، فراخوانی میشود.
4- برای نمایش صفحه به صورت Popup کافی است بجای اینکه View ما یک Content Page باشد، یک PopupPage باشد (برای درک بهتر، فایل IntroView.xaml را در فولدر Views باز کنید).
حتی میتوانید Animation مربوط به باز شدن پاپ آپ را هم کاملا Customize کنید. مثلا زمان باز شدن، از سمت راست صفحه وارد شود و زمان خارج شدن، Fade out شود. باز کردن Popup در Navigation Page معنی نمیدهد، پس با Nav/ در اینجا کاری نداریم. در مثال ما، بعد از لاگین میخواهیم یک صفحه Intro شامل هشدارها و راهنماییهای اولیه را در قالب Popup به کاربر نمایش دهیم. Popupها میتوانند همچون Content Pageها، دارای View Model باشند و مواردی چون OnNavigatedTo، ارسال پارامتر و هر آنچه که گفته شد، در مورد آنها نیز صدق میکند.
5- برای Master/Detail کافی است بجای Nav/HelloWorld/ از MasterDetail/Nav/HelloWorld/ استفاده کنید. این عمل باعث میشود HelloWorld در داخل Navigation Page و Navigation Page داخل Master Detail باز شود. از این سادهتر امکان ندارد!
برای تغییر UI مربوط به Master که از سمت چپ باز میشود، فایل XamAppMasterDetailView.xaml را تغییر دهید.
در قسمت بعدی به جزئیات Binding خواهیم پرداخت.
<!-- https://github.com/dotnet/sdk/issues/1458#issuecomment-420456386 --> <Target Name="_ResolveCopyLocalNuGetPackagePdbsAndXml" Condition="$(CopyLocalLockFileAssemblies) == true" AfterTargets="ResolveReferences"> <ItemGroup> <ReferenceCopyLocalPaths Include="@(ReferenceCopyLocalPaths->'%(RootDir)%(Directory)%(Filename).pdb')" Condition="'%(ReferenceCopyLocalPaths.NuGetPackageId)' != '' and Exists('%(RootDir)%(Directory)%(Filename).pdb')" /> <ReferenceCopyLocalPaths Include="@(ReferenceCopyLocalPaths->'%(RootDir)%(Directory)%(Filename).xml')" Condition="'%(ReferenceCopyLocalPaths.NuGetPackageId)' != '' and Exists('%(RootDir)%(Directory)%(Filename).xml')" /> </ItemGroup> </Target>
سری آموزشی مقدماتی Web API
Our beginner's guide to building Web APIs with ASP.NET Core is designed to provide you with the foundation you need to start building Web APIs with .NET in a collection of short, pragmatic collection of videos. Web APIs have become a critical component in almost every type of software we use today. In this introductory video series, we will walk you through the fundamental concepts you need to know to get started with building Web APIs using ASP.NET Core. We will cover topics such as routing, validation, working with data, and much more.
So when Microsoft acquired Xamarin in 2016 and started integrating the Xamarin Visual Studio plugins more with the standard VS features, I knew I had to try and switch over to take advantage of the powerful IDE and language. Some of the immediate benefits I gained from the switch are:
- Simple asynchronous programming
- Access to powerful plugins like ReSharper
- Freedom to work in Windows or OSX
- Access to powerful debugging tools for the Android on Windows (debugging iOS on Mac side is good but can be buggy).
- Access to built in NuGet package management for third party libraries
نظرات یک استفاده کننده از TFS پس از سه سال تجربه کار با آن
اما اخیرا در نسخه ویژوال استودیو 2012 احساس کردم کار با TFS در گنگتر شده است. (منظورم Team Explorer آن هست) نسخه نهایی TFS 2012 را دریافت کردهام اما هنوز برنامهای برای مهاجرت به آن از نسخه 2010 نداریم. بسیاری از مواردی که در این لینک به شکل انتقادی بیان شدهاند قرار است در نسخه جدید رفع شده و یا بهبود یابند.
به هر حال نظرات متفاوتاند و هر نظری محترم. هر کسی از دید نیازهای خود میسنجد و از این لحاظ اینجانب TFS رو محصولی قوی و کارساز میدونم.
دوراهی انتخاب NHibernate و Entityframework
- کد نهایی تمیزتر. چون کلاسها را خودتان طراحی میکنید و توسط ابزارها به صورت خودکار تولید نمیشوند، کنترل بیشتر و نهایتا کیفیت بالاتری دارند.
- ساده است. درگیر نگهداری edmx modelها نخواهید بود. به روز رسانی بانک اطلاعاتی آن هم میتواند کاملا خودکار شود.
2 - دیتاست که کلا کارآیی بالایی نداره. اما ... نهایتا مطمئن هستم خروجی EF (به همراه تمام best practices لحاظ شده در آن) سرعت بالاتری از کلاسهای دست ساز sql helper موجود در وب دارد. برای مثال سطح اول کش آن خیلی از کوئریها را مجددا به بانک اطلاعاتی ارسال نمیکند. قابلیت اجرای به تعویق افتاده کوئریهای لینک امکان تهیه کوئریهای بسیار پیچیده را در یک رفت و برگشت مهیا میکند. کاری که با sql helperهای معمولی نیازی به چندبار رفت و برگشت دارد. قابلیتهای lazy loading آن میتواند مصرف حافظه و بار سرور را درصورت استفاده صحیح کاهش دهد. کوئریهای آن strongly typed و پارامتری هستند (تحت نظر کامپایلر + امنیت + سرعت (کوئریهای پارامتری مانند رویههای ذخیره شده کش میشوند)). به صورت پیش فرض از تراکنشها استفاده میکند و ... خیلی از الگوهای مفید دیگر که چندین سال باید وقت صرف کنید تا نمونه آنها را پیاده سازی کنید. یعنی کار اصولی با بانک اطلاعاتی صرفا یک select ساده نیست که بر اساس آن کارآیی و یا بهتر بودن روشی را مشخص کنید.