It’s time to get serious about improving your programming skills. Let’s do it!
That’s an easy career improvement goal to give oneself, but “become a kick-$!! programmer” is not a simple goal. For one thing, saying, “I want to get better” assumes that you recognize what “better” looks like. Plus, too many people aim for improvement without any sense of how to get there.
ابتدا یک پروژه Asp.Net MVC ایجاد کنید. در فولدر scripts تمام فایلهای جاوااسکریپ پروژه قرار خواهند داشت. اگر قصد داشته باشیم که فایلهای جاوااسکریپی سایر فریم ورکها را استفاده نماییم (مثل backbone.js و ExtJs و...) برای طبقه بندی بهتر فایل ها، بهتر است که یک فولدر با نامی مشخص بسازیم و فایلهای مورد نیاز را در آن قرار دهیم. البته اگر از nuget برای نصب این فریم ورکها استفاده نمایید عموما این کار انجام خواهد شد.
حال با استفاده از Package Manager Console و اجرای دستور زیر، اقدام به نصب requireJs کنید
PM> Install-package requireJs
یک فولدر به نام MyFiles در فولدر Scripts بسازید و فایلهای purchase.js و product.js و credits.js در پروژه قبل را در آن کپی نمایید. کد فایلهای پروژه قبل به صورت زیر بوده است:
purchase.js
define(["credits","products"], function(credits,products) { console.log("Function : purchaseProduct"); return { purchaseProduct: function() { var credit = credits.getCredits(); if(credit > 0){ products.reserveProduct(); alert('purchase done');' return true;
} alert('purchase cancel'); return false; } } });
products.js
define(function(products) { return { reserveProduct: function() { console.log("Function : reserveProduct"); return true; } } });
define(function() { console.log("Function : getCredits"); return { getCredits: function() { var credits = "100"; return credits; } } });
برای قدم بعدی، در متد RegisterBundles فایل bundleConfig پروژه دستور زیر را وارد نمایید:
bundles.Add( new ScriptBundle( "~/bundles/require" ).Include( "~/Scripts/require.js" ) );
حال برای استفاده و لود ماژول purchase در انتهای فایل Index فولدر Home تغییرات زیر را اعمال نمایید:
@section scripts { <script type="text/javascript"> require(['purchase'], function (purchase) { purchase.purchaseProduct(); }); </script> }
In this article, we will learn how to use JQuery Datatable in ASP.NET Core with Server Side Processing. We will also be building a simple real-world implementation to help understand JQuery Datatable to it’s fullest. You can find the source code of the entire implementation here. Let’s begin
انتشار TypeScript 5.6
کامپایل نشدن فایل T4
PM> update-package T4MVC -Reinstall -ProjectName MVC5.Web PM> update-package Microsoft.AspNet.Mvc -ProjectName MVC5.Web PM> update-package Microsoft.Web.Infrastructure -ProjectName MVC5.Web
انتشار WinJS 4.0
شروع به کار با RavenDB
- مروری بر مفاهیم مقدماتی NoSQL
- ردهها و انواع مختلف بانکهای اطلاعاتی NoSQL
- چه زمانی بهتر است از بانکهای اطلاعاتی NoSQL استفاده کرد و چه زمانی خیر؟
لطفا یکبار این پیشنیازها را پیش از شروع به کار مطالعه نمائید؛ چون بسیاری از مفاهیم پایهای و اصطلاحات مرسوم دنیای NoSQL در این سه قسمت بررسی شدهاند و از تکرار مجدد آنها در اینجا صرفنظر خواهد شد.
RavenDB چیست؟
RavenDB یک بانک اطلاعاتی سورس باز NoSQL سندگرای تهیه شده با دات نت است. ساختار کلی بانکهای اطلاعاتی NoSQL سندگرا، از لحاظ نحوه ذخیره سازی اطلاعات، با بانکهای اطلاعاتی رابطهای متداول، کاملا متفاوت است. در اینگونه بانکهای اطلاعاتی، رکوردهای اطلاعات، به صورت اشیاء JSON ذخیره میشوند. اشیاء JSON یا JavaScript Object Notation بسیار شبیه به anonymous objects سی شارپ هستند. JSON روشی است که توسط آن JavaScript اشیاء خود را معرفی و ذخیره میکند. به عنوان رقیبی برای XML مطرح است؛ نسبت به XML اندکی فشردهتر بوده و عموما دارای اسکیمای خاصی نیست و در بسیاری از اوقات تفسیر المانهای آن به مصرف کننده واگذار میشود.
در JSON عموما سه نوع المان پایه مشاهده میشوند:
- اشیاء که به صورت {object} تعریف میشوند.
- مقادیر "key":"value" که شبیه به نام خواص و مقادیر آنها در دات نت هستند.
- و آرایهها به صورت [array]
همچنین ترکیبی از این سه عنصر یاد شده نیز همواره میسر است. برای مثال، یک key مشخص میتواند دارای مقداری حاوی یک آرایه یا شیء نیز باشد.
JSON: JavaScript Object Notation document :{ key: "Value", another_key: { name: "embedded object" }, some_date: new Date(), some_number: 12 } C# anonymous object var Document = new { Key= "Value", AnotherKey= new { Name = "embedded object" }, SomeDate = DateTime.Now(), SomeNumber = 12 };
یک نکته مهم
اگر پیشنیازهای بحث را مطالعه کرده باشید، حتما بارها با این جمله که دنیای NoSQL از تراکنشها پشتیبانی نمیکند، برخورد داشتهاید. این مطلب در مورد RavenDB صادق نیست و این بانک اطلاعاتی NoSQL خاص، از تراکنشها پشتیبانی میکند. RavenDB در Document store خود ACID عملکرده و از تراکنشها پشتیبانی میکند. اما تهیه ایندکسهای آن بر مبنای مفهوم عاقبت یک دست شدن عمل میکند.
مجوز استفاده از RavenDB
هرچند مجموعه سرور و کلاینت RavenDB سورس باز هستند، اما این مورد به معنای رایگان بودن آن نیست. مجوز استفاده از RavenDB نوع خاصی به نام AGPL است. به این معنا که یا کل کار مشتق شده خود را باید به صورت رایگان و سورس باز ارائه دهید و یا اینکه مجوز استفاده از آنرا برای کارهای تجاری بسته خود خریداری نمائید. نسخه استاندارد آن نزدیک به هزار دلار است و نسخه سازمانی آن نزدیک به 2800 دلار به ازای هر سرور.
شروع به نوشتن اولین برنامه کار با RavenDB
ابتدا یک پروژه کنسول ساده را آغاز کنید. سپس کلاسهای مدل زیر را به آن اضافه نمائید:
using System.Collections.Generic; namespace RavenDBSample01.Models { public class Question { public string By { set; get; } public string Title { set; get; } public string Content { set; get; } public List<Comment> Comments { set; get; } public List<Answer> Answers { set; get; } public Question() { Comments = new List<Comment>(); Answers = new List<Answer>(); } } } namespace RavenDBSample01.Models { public class Comment { public string By { set; get; } public string Content { set; get; } } } namespace RavenDBSample01.Models { public class Answer { public string By { set; get; } public string Content { set; get; } } }
PM> Install-Package RavenDB.Client PM> Install-Package RavenDB.Server
اکنون به پوشه packages\RavenDB.Server.2.5.2700\tools مراجعه کرده و برنامه Raven.Server.exe را اجرا کنید تا سرور RavenDB شروع به کار کند. این سرور به صورت پیش فرض بر روی پورت 8080 اجرا میشود. از این جهت که در RavenDB نیز همانند سایر Document Stores مطرح، امکان دسترسی به اسناد از طریق REST API و Urlها وجود دارد.
البته لازم به ذکر است که RavenDB در 4 حالت برنامه کنسول (همین سرور فوق)، نصب به عنوان یک سرویس ویندوز NT، هاست شدن در IIS و حالت مدفون شده یا Embedded قابل استفاده است.
خوب؛ همین اندازه برای برپایی اولیه RavenDB کفایت میکند.
using Raven.Client.Document; using RavenDBSample01.Models; namespace RavenDBSample01 { class Program { static void Main(string[] args) { using (var store = new DocumentStore { Url = "http://localhost:8080" }.Initialize()) { using (var session = store.OpenSession()) { session.Store(new Question { By = "users/Vahid", Title = "Raven Intro", Content = "Test...." }); session.SaveChanges(); } } } } }
کار با ایجاد یک DocumentStore که به آدرس سرور اشاره میکند و کار مدیریت اتصالات را برعهده دارد، شروع خواهد شد. اگر نمیخواهید Url را درون کدهای برنامه مقدار دهی کنید، میتوان از فایل کانفیگ برنامه نیز برای این منظور کمک گرفت:
<connectionStrings> <add name="ravenDB" connectionString="Url=http://localhost:8080"/> </connectionStrings>
سپس با ایجاد Session در حقیقت یک Unit of work آغاز میشود که درون آن میتوان انواع و اقسام دستورات را صادر نمود و سپس در پایان کار، با فراخوانی SaveChanges، این اعمال ذخیره میگردند. در RavenDB یک سشن باید طول عمری کوتاه داشته باشد و اگر تعداد عملیاتی که در آن صادر کردهاید، زیاد است با خطای زیر متوقف خواهید شد:
The maximum number of requests (30) allowed for this session has been reached.
در یک برنامه واقعی، ایجاد DocumentStore یکبار در آغاز کار برنامه باید انجام گردد. اما هر سشن یا هر واحد کاری آن، به ازای تراکنشهای مختلفی که باید صورت گیرند، بر روی این DocumentStore، ایجاد شده و سپس بسته خواهند شد. برای مثال در یک برنامه ASP.NET، در فایل Global.asax در زمان آغاز برنامه، کار ایجاد DocumentStore انجام شده و سپس به ازای هر درخواست رسیده، یک سشن RavenDB ایجاد و در پایان درخواست، این سشن آزاد خواهد شد.
برنامه را اجرا کنید، سپس به کنسول سرور RavenDB که پیشتر آنرا اجرا نمودیم مراجعه نمائید تا نمایی از عملیات انجام شده را بتوان مشاهده کرد:
Raven is ready to process requests. Build 2700, Version 2.5.0 / 6dce79a Server started in 14,438 ms Data directory: D:\Prog\RavenDBSample01\packages\RavenDB.Server.2.5.2700\tools\Database\System HostName: <any> Port: 8080, Storage: Esent Server Url: http://localhost:8080/ Available commands: cls, reset, gc, q Request # 1: GET - 514 ms - <system> - 404 - /docs/Raven/Replication/Destinations Request # 2: GET - 763 ms - <system> - 200 - /queries/?&id=Raven%2FHilo%2Fquestions&id=Raven%2FServerPrefixForHilo Request # 3: PUT - 185 ms - <system> - 201 - /docs/Raven/Hilo/questions Request # 4: POST - 103 ms - <system> - 200 - /bulk_docs PUT questions/1
عملیات PUT حتما نیاز به یک Id از پیش مشخص دارد و این Id، پیشتر در سطری که Hilo در آن ذکر شده (یکی از الگوریتمهای محاسبه Id در RavenDB)، محاسبه گردیده است. برای نمونه در اینجا الگوریتم Hilo مقدار "questions/1" را به عنوان Id محاسبه شده بازگشت داده است.
در سطری که عملیات Post به آدرس bulk_docs سرور ارسال گردیده است، کار ارسال یکباره چندین شیء JSON برای کاهش رفت و برگشتها به سرور انجام میشود.
و برای کوئری گرفتن مقدماتی از اطلاعات ثبت شده میتوان نوشت:
using (var session = store.OpenSession()) { var question1 = session.Load<Question>("questions/1"); Console.WriteLine(question1.By); }
نگاهی به بانک اطلاعاتی ایجاد شده
در همین حال که سرور RavenDB در حال اجرا است، مرورگر دلخواه خود را گشوده و سپس آدرس http://localhost:8080 را وارد نمائید. بلافاصله، کنسول مدیریتی تحت وب این بانک اطلاعاتی که با سیلورلایت نوشته شده است، ظاهر خواهد شد:
و اگر بر روی هر سطر اطلاعات دوبار کلیک کنید، به معادل JSON آن نیز خواهید رسید:
اینبار برنامه را به صورت زیر تغییر دهید تا روابط بین کلاسها را نیز پیاده سازی کند:
using System; using Raven.Client.Document; using RavenDBSample01.Models; namespace RavenDBSample01 { class Program { static void Main(string[] args) { using (var store = new DocumentStore { Url = "http://localhost:8080" }.Initialize()) { using (var session = store.OpenSession()) { var question = new Question { By = "users/Vahid", Title = "Raven Intro", Content = "Test...." }; question.Answers.Add(new Answer { By = "users/Farid", Content = "بررسی میشود" }); session.Store(question); session.SaveChanges(); } using (var session = store.OpenSession()) { var question1 = session.Load<Question>("questions/1"); Console.WriteLine(question1.By); } } } } }
اگر برنامه فوق را اجرا کرده و به ساختار اطلاعات ذخیره شده نگاهی بیندازیم به شکل زیر خواهیم رسید:
نکته جالبی که در اینجا وجود دارد، عدم نیاز به join نویسی برای دریافت اطلاعات وابسته به یک شیء است. اگر سؤالی وجود دارد، پاسخهای به آن و یا سایر نظرات، یکجا داخل همان سؤال ذخیره میشوند و به این ترتیب سرعت دسترسی نهایی به اطلاعات بیشتر شده و همچنین قفل گذاری روی سایر اسناد کمتر. این مساله نیز به ذات NoSQL و یا غیر رابطهای RavenDB بر میگردد. در بانکهای اطلاعاتی NoSQL، مفاهیمی مانند کلیدهای خارجی، JOIN بین جداول و امثال آن وجود خارجی ندارند. برای نمونه اگر به کلاسهای مدلهای برنامه دقت کرده باشید، خبری از وجود Id در آنها نیست. RavenDB یک Document store است و نه یک Relation store. در اینجا کل درخت تو در توی خواص یک شیء دریافت و به صورت یک سند ذخیره میشود. به حاصل این نوع عملیات در دنیای بانکهای اطلاعاتی رابطهای، Denormalized data هم گفته میشود.
البته میتوان به کلاسهای تعریف شده خاصیت رشتهای Id را نیز اضافه کرد. در این حالت برای مثال در حالت فراخوانی متد Load، این خاصیت رشتهای، با Id تولید شده توسط RavenDB مانند "questions/1" مقدار دهی میشود. اما از این Id برای تعریف ارجاعات به سؤالات و پاسخهای متناظر استفاده نخواهد شد؛ چون تمام آنها جزو یک سند بوده و داخل آن قرار میگیرند.
In this video we perform a full step by step build of a .NET MAUI App that we test on both Windows and Android. The app interacts with a separate .NET 6 API that we also build step by step.
Level: Beginner
⏲️ Time Codes ⏲️
Theory
- 0:48 Welcome
- 03:13 App demo
- 06:07 Course overview
- 09:14 Ingedients
- 10:10 What is .NET MAUI?
- 12:48 How MAUI works
- 15:14 MAUI project anatomy
- 19:47 MAUI App start up sequence
- 22:29 UI Conepts
- 28:21 XAML vs C#
- 30:29 Solution Architecture
- 31:41 Application Architecture
API Build
- 35:31 API Project Set up
- 42:41 API Model definition
- 44:47 API Db Context
- 47:13 Connection String
- 52:19 Migrations
- 56:31 API Read Endpoint
- 1:01:58 API Create Endpoint
- 1:08:15 API Update Endpoint
- 1:12:57 API Delete Endpoint
MAUI App Build
- 1:17:21 MAUI App Project Set up
- 1:21:00 Android Device Manager
- 1:25:08 MAUI Model definition
- 1:31:16 Data Service Interface
- 1:35:40 Data Service Implementation
- 1:47:27 Data Service Read Method
- 1:53:34 Data Service Create Method
- 1:58:48 Data Service Delete Method
- 2:01:53 Data Service Update Method
- 2:05:41 Android environment config
- 2:11:00 Architecture check point
- 2:11:54 Register MainPage for DI
- 2:14:13 MainPage code-behind
- 2:21:03 MainPage XAML Layout
- 2:30:19 Re-work MainPage layout
- 2:35:12 Add another page (ManagePage)
- 2:38:01 Adding a Route
- 2:30:01 Regiter ManagePage for DI
- 2:40:29 Complete MainPage code-behind
- 2:45:12 ManagePage code-behind
- 2:51:16 QueryProperty
- 2:57:34 ManagePage XMAL
- 3:07:56 Run on Windows
- 3:09:30 Re-work ManagePage layout
- 3:16:26 Using HttpClientFactory
Outro
- 3:21:02 Wrap up and thanks
- 3:21:31 Supporter Credits