در حالتی که grantType کلاینت ResourceOwnerPassword و نوع توکن jwt میباشد , چگونه میتوان sign out را پیاده سازی کرد؟متد RevokeTokenAsync فقط برای رفرنس توکن استفاده میشه.
برای نمایش اول کار: جمع کل ریشه اصلی مساوی است با جمع فرزندانی که والد غیر null دارند. یک کوئری سبک بیشتر نیست. مابقی جمعهای درخت رو میشه سمت کلاینت مدیریت کرد.
نظرات مطالب
ASP.NET Web API - قسمت اول
سلام
یک سوال مهم داشتم، آیا استفاده از web api در Windows Form مانند WCF ممکن است، یعنی پروژه ما هم هاست و هم کلاینت رو MVC یا ASP.Net نیست، اگه میشه یه منبع معرفی کنید.
یک نکتهی تکمیلی: نحوهی انتخاب یک المنت در Vue.js در Vue.js چندین روش برای انتخاب یک المنت وجود دارند که در ادامه آنها را مورد بررسی قرار میدهیم.
کد زیر را در نظر بگیرید، ما قصد داریم value موجود در input را نمایش دهیم.
و میتوان بصورتی که در مثال کد استفاده شده، آن را خلاصه نمود.
روش اول: با استفاده از جاوا اسکریپت
<!DOCTYPE html> <head> <meta charset="UTF-8"> <title>Vue.js گرفتن یک المنت در </title> </head> <body> <div id="main"> <input type="text" name="fullName" id="fullName"> <button @click='getFullNameValue()'>Show Me</button> </div> <script src="https://cdn.jsdelivr.net/npm/vue"></script> <script> new Vue({ el: '#main', data() { return { } }, methods: { getFullNameValue() { let fullNameValue = document.querySelector('#fullName').value; alert(fullNameValue); } } }); </script> </body> </html>
با استفاده از دستور زیر در جاوا اسکریپت براحتی میتوانیم یک المنت را انتخاب کنیم و آن را به یک متغیر انتساب دهیم.
let fullNameValue = document.querySelector('#fullName')
روش دوم: انتخاب یک المنت با جی کوئری (با سلکتور دلخواه)
getFullNameValue() { //let fullNameValue = document.querySelector('#fullName').value; let fullNameValue = $('#fullName'); alert(fullNameValue.val()); }
روش سوم: انتخاب یک المنت در حیطه نمونه سازی شده Vue.js
getFullNameValue() { //let fullNameValue = document.querySelector('#fullName').value; //let fullNameValue = $('#fullName').val(); let fullNameValue = this.$el.querySelector('#fullName'); alert(fullNameValue.value ); }
روش چهارم: انتخاب یک المنت از طریق امکان ref در Vue.js
<!DOCTYPE html> <head> <meta charset="UTF-8"> <title>Vue.js گرفتن یک المنت در </title> </head> <body> <div id="main"> <input type="text" name="fullName" id="fullName" ref="refFullName"> <button @click='getFullNameValue()'>Show Me</button> </div> <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/vue"></script> <script> new Vue({ el: '#main', data() { return { } }, methods: { getFullNameValue() { //let fullNameValue = document.querySelector('#fullName').value; //let fullNameValue = $('#fullName').val(); //let fullNameValue = this.$el.querySelector('#fullName').value; let fullNameValue = this.$refs.refFullName; alert(fullNameValue.value); } } }); </script> </body> </html>
نتیجه گیری:
از لحاظ performance روش سوم و چهارم بهینه میباشند؛ زیرا فقط در حیطه نمونه سازی شده Vue.js مربوطه جستجوی المنت را انجام میدهند. درحالیکه در روش اول و دوم کل DOM مورد بررسی قرار میگیرد. روش چهارم بخاطر سهولت نوشتاری بهتر از سایر موارد میباشد.
چند نکته در مورد کد فوق:
A) در ES6 نیازی به نوشتن کلمه کلیدی function برای تعریف یک متد نیست.
getFullNameValue: function() { ... }
B) در ورژن جدید Vue.js بجای استفاده از دایرکتیو v-on ( کد زیر ) برای تعریف یک رویداد میتوان از @ استفاه نمود. در مثال مورد استفادهی مقاله از @ استفاده شده است.
<button v-on:click='getFullNameValue()'>Show Me</button>
مطالب دورهها
شروع به کار با 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 مشخص میتواند دارای مقداری حاوی یک آرایه یا شیء نیز باشد.
به این ترتیب میتوان به یک ساختار دلخواه و بدون اسکیما، از هر سند به سند دیگری رسید. اغلب بانکهای اطلاعاتی سندگرا، اینگونه اسناد را در زمان ذخیره سازی، به یک سری binary tree تبدیل میکنند تا تهیه کوئری بر روی آنها بسیار سریع شود. مزیت دیگر استفاده از JSON، سادگی و سرعت بالای Serialize و Deserialize اطلاعات آن برای ارسال به کلاینتها و یا دریافت آنها است؛ به همراه فشردهتر بودن آن نسبت به فرمتهای مشابه دیگر مانند XML.
یک نکته مهم
اگر پیشنیازهای بحث را مطالعه کرده باشید، حتما بارها با این جمله که دنیای NoSQL از تراکنشها پشتیبانی نمیکند، برخورد داشتهاید. این مطلب در مورد RavenDB صادق نیست و این بانک اطلاعاتی NoSQL خاص، از تراکنشها پشتیبانی میکند. RavenDB در Document store خود ACID عملکرده و از تراکنشها پشتیبانی میکند. اما تهیه ایندکسهای آن بر مبنای مفهوم عاقبت یک دست شدن عمل میکند.
مجوز استفاده از RavenDB
هرچند مجموعه سرور و کلاینت RavenDB سورس باز هستند، اما این مورد به معنای رایگان بودن آن نیست. مجوز استفاده از RavenDB نوع خاصی به نام AGPL است. به این معنا که یا کل کار مشتق شده خود را باید به صورت رایگان و سورس باز ارائه دهید و یا اینکه مجوز استفاده از آنرا برای کارهای تجاری بسته خود خریداری نمائید. نسخه استاندارد آن نزدیک به هزار دلار است و نسخه سازمانی آن نزدیک به 2800 دلار به ازای هر سرور.
شروع به نوشتن اولین برنامه کار با RavenDB
ابتدا یک پروژه کنسول ساده را آغاز کنید. سپس کلاسهای مدل زیر را به آن اضافه نمائید:
سپس به کنسول پاور شل نیوگت در ویژوال استودیو مراجعه کرده و دستورات ذیل را جهت افزوده شدن وابستگیهای مورد نیاز RavenDB، صادر کنید:
به این ترتیب بستههای کلاینت (مورد نیاز جهت برنامه نویسی) و سرور RavenDB به پروژه جاری اضافه خواهند شد (نگارش 2.5 در زمان نگارش این مطلب؛ جمعا نزدیک به 75 مگابایت).
اکنون به پوشه packages\RavenDB.Server.2.5.2700\tools مراجعه کرده و برنامه Raven.Server.exe را اجرا کنید تا سرور RavenDB شروع به کار کند. این سرور به صورت پیش فرض بر روی پورت 8080 اجرا میشود. از این جهت که در RavenDB نیز همانند سایر Document Stores مطرح، امکان دسترسی به اسناد از طریق REST API و Urlها وجود دارد.
البته لازم به ذکر است که RavenDB در 4 حالت برنامه کنسول (همین سرور فوق)، نصب به عنوان یک سرویس ویندوز NT، هاست شدن در IIS و حالت مدفون شده یا Embedded قابل استفاده است.
خوب؛ همین اندازه برای برپایی اولیه RavenDB کفایت میکند.
اکنون کدهای برنامه کنسول را به نحو فوق برای ذخیره سازی اولین سند خود، تغییر دهید.
کار با ایجاد یک DocumentStore که به آدرس سرور اشاره میکند و کار مدیریت اتصالات را برعهده دارد، شروع خواهد شد. اگر نمیخواهید Url را درون کدهای برنامه مقدار دهی کنید، میتوان از فایل کانفیگ برنامه نیز برای این منظور کمک گرفت:
در این حالت باید خاصیت ConnectionStringName شیء DocumentStore را مقدار دهی نمود.
سپس با ایجاد Session در حقیقت یک Unit of work آغاز میشود که درون آن میتوان انواع و اقسام دستورات را صادر نمود و سپس در پایان کار، با فراخوانی SaveChanges، این اعمال ذخیره میگردند. در RavenDB یک سشن باید طول عمری کوتاه داشته باشد و اگر تعداد عملیاتی که در آن صادر کردهاید، زیاد است با خطای زیر متوقف خواهید شد:
البته این نوع محدودیتها عمدی است تا برنامه نویس به طراحی بهتری برسد.
در یک برنامه واقعی، ایجاد DocumentStore یکبار در آغاز کار برنامه باید انجام گردد. اما هر سشن یا هر واحد کاری آن، به ازای تراکنشهای مختلفی که باید صورت گیرند، بر روی این DocumentStore، ایجاد شده و سپس بسته خواهند شد. برای مثال در یک برنامه ASP.NET، در فایل Global.asax در زمان آغاز برنامه، کار ایجاد DocumentStore انجام شده و سپس به ازای هر درخواست رسیده، یک سشن RavenDB ایجاد و در پایان درخواست، این سشن آزاد خواهد شد.
برنامه را اجرا کنید، سپس به کنسول سرور RavenDB که پیشتر آنرا اجرا نمودیم مراجعه نمائید تا نمایی از عملیات انجام شده را بتوان مشاهده کرد:
زمانیکه سرور RavenDB در حالت دیباگ در حال اجرا باشد، لاگ کلیه اعمال انجام شده را در کنسول آن میتوان مشاهده نمود. همانطور که مشاهده میکنید، یک کلاینت RavenDB با این بانک اطلاعاتی با پروتکل HTTP و یک REST API ارتباط برقرار میکند. برای نمونه، کلاینت در اینجا با اعمال یک HTTP Verb خاص به نام PUT، اطلاعات را درون بانک اطلاعاتی ذخیره کرده است. تبادل اطلاعات نیز با فرمت JSON انجام میشود.
عملیات PUT حتما نیاز به یک Id از پیش مشخص دارد و این Id، پیشتر در سطری که Hilo در آن ذکر شده (یکی از الگوریتمهای محاسبه Id در RavenDB)، محاسبه گردیده است. برای نمونه در اینجا الگوریتم Hilo مقدار "questions/1" را به عنوان Id محاسبه شده بازگشت داده است.
در سطری که عملیات Post به آدرس bulk_docs سرور ارسال گردیده است، کار ارسال یکباره چندین شیء JSON برای کاهش رفت و برگشتها به سرور انجام میشود.
و برای کوئری گرفتن مقدماتی از اطلاعات ثبت شده میتوان نوشت:
نگاهی به بانک اطلاعاتی ایجاد شده
در همین حال که سرور RavenDB در حال اجرا است، مرورگر دلخواه خود را گشوده و سپس آدرس http://localhost:8080 را وارد نمائید. بلافاصله، کنسول مدیریتی تحت وب این بانک اطلاعاتی که با سیلورلایت نوشته شده است، ظاهر خواهد شد:
و اگر بر روی هر سطر اطلاعات دوبار کلیک کنید، به معادل JSON آن نیز خواهید رسید:
اینبار برنامه را به صورت زیر تغییر دهید تا روابط بین کلاسها را نیز پیاده سازی کند:
در اینجا یک سؤال به همراه پاسخی به آن تعریف شده است. همچنین در مرحله بعد، نحوه کوئری گرفتن مقدماتی از اطلاعات را بر اساس Id سند مرتبط، مشاهده میکنید. چون یک Session، الگوی واحد کار را پیاده سازی میکند، اگر پس از Load یک سند، خواصی از آنرا تغییر دهیم و در پایان Session متد SaveChanges فراخوانی شود، به صورت خودکار این تغییرات به بانک اطلاعاتی نیز اعمال خواهند شد (روش به روز رسانی اطلاعات). این مورد بسیار شبیه است به مباحث پایه ای Change tracking که در بسیاری از ORMهای معروف تاکنون پیاده سازی شدهاند. روش حذف اطلاعات نیز به همین ترتیب است. ابتدا سند مورد نظر یافت شده و سپس متد session.Delete بر روی این شیء یافت شده فراخوانی گردیده و در پایان سشن باید SaveChanges جهت نهایی شدن تراکنش فراخوانی گردد.
اگر برنامه فوق را اجرا کرده و به ساختار اطلاعات ذخیره شده نگاهی بیندازیم به شکل زیر خواهیم رسید:
نکته جالبی که در اینجا وجود دارد، عدم نیاز به join نویسی برای دریافت اطلاعات وابسته به یک شیء است. اگر سؤالی وجود دارد، پاسخهای به آن و یا سایر نظرات، یکجا داخل همان سؤال ذخیره میشوند و به این ترتیب سرعت دسترسی نهایی به اطلاعات بیشتر شده و همچنین قفل گذاری روی سایر اسناد کمتر. این مساله نیز به ذات NoSQL و یا غیر رابطهای RavenDB بر میگردد. در بانکهای اطلاعاتی NoSQL، مفاهیمی مانند کلیدهای خارجی، JOIN بین جداول و امثال آن وجود خارجی ندارند. برای نمونه اگر به کلاسهای مدلهای برنامه دقت کرده باشید، خبری از وجود Id در آنها نیست. RavenDB یک Document store است و نه یک Relation store. در اینجا کل درخت تو در توی خواص یک شیء دریافت و به صورت یک سند ذخیره میشود. به حاصل این نوع عملیات در دنیای بانکهای اطلاعاتی رابطهای، Denormalized data هم گفته میشود.
البته میتوان به کلاسهای تعریف شده خاصیت رشتهای Id را نیز اضافه کرد. در این حالت برای مثال در حالت فراخوانی متد Load، این خاصیت رشتهای، با Id تولید شده توسط RavenDB مانند "questions/1" مقدار دهی میشود. اما از این Id برای تعریف ارجاعات به سؤالات و پاسخهای متناظر استفاده نخواهد شد؛ چون تمام آنها جزو یک سند بوده و داخل آن قرار میگیرند.
- مروری بر مفاهیم مقدماتی 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 برای تعریف ارجاعات به سؤالات و پاسخهای متناظر استفاده نخواهد شد؛ چون تمام آنها جزو یک سند بوده و داخل آن قرار میگیرند.
سلام
پیاده سازی Single Sign on در این سیستم کجا کار قرار داره؟ در واقع چطور میشه پیاده سازی ش کرد؟
در سیستم membership قبلی، اگر کلید اپلیکیشن رو در وب کانفیگ برنامه هاتون که دامین هاشون مشترک بود (در واقع ساب دامین ها)، یکسان وارد میکردی، برنامهها بصورت SSO کار میکرد و احتیاجی به هیچ کاری نداشت. حالا در سیستم جدید همون روش جواب میده؟ برای برنامههای با دامینهای متفاوت چطور؟
نظرات مطالب
EF Code First #12
ViewModel متناظر است با اشیاء یک View که الزاما تطابق یک به یکی با Domain Model و موجودیتهای بانک اطلاعاتی ندارند. مثلا یک صفحه تعویض پسورد هست و فقط یک فیلد پسورد داره. اینجا در معرض دید قرار دادن کل موجودیت کاربر در یک برنامه وب MVC اشتباه است چون به سادگی مورد حمله واقع خواهد شد. خلاصه هر دو مورد ViewModel و Domain model نیاز به اعتبارسنجی دارند؛ به هر روشی که صلاح میدونید.
نهایتا اطلاعات ViewModel در حالت Post، به اطلاعات Model انتساب داده میشه. یا دستی و یا مثلا توسط AutoMapper ؛ در این حالت هم هر طور که راحت هستید عمل کنید. قانون یا روش بهتری برای این نوع انتسابها وجود نداره.
نهایتا اطلاعات ViewModel در حالت Post، به اطلاعات Model انتساب داده میشه. یا دستی و یا مثلا توسط AutoMapper ؛ در این حالت هم هر طور که راحت هستید عمل کنید. قانون یا روش بهتری برای این نوع انتسابها وجود نداره.
مطالب
NOSQL قسمت اول
در این پست نگاهی کلی به ویژگیهای پایگاههای داده NOSql خواهیم
داشت و با بررسی تاریخچه و دلیل پیدایش این سیستمها آشنا خواهیم شد.
با فراگیر شدن اینترنت در سالهای اخیر و افزایش کاربران ، سیستمهای RDBMS جوابگوی نیازهای برنامهنویسان در حوزهی وب نبودند زیرا نیاز به نگهداری دادهها با حجم بالا و سرعت خواندن و نوشتن بالا از جمله نقط ضعف سیستمهای RDBMS میباشد ، چرا که با افزایش شدید کاربران دادهها اصولا به صورت منطقی ساختار یکدست خود را جهت نگهداری از دست میدهند و به این ترتیب عملیات نرمال سازی منجر به ساخت جداول زیادی میشود که نتیجه آن برای هر کوئری عملیات Joinهای متعدد میباشد که سرعت خواندن و نوشتن را به خصوص برای برنامههای با گسترهی وب پایین میآورد و مشکلات دیگری در سیستمهای RDBMS که ویژگیهای سیستمهای NoSql مشخص کننده آن مشکلات است که در ادامه به آن میپردازیم.
طبق تعریف کلی پایگاه داده NOSql عبارت است از:
نسل بعدی پایگاه داده (نسل از بعد RDBMS ) که اصولا دارای چند ویژگی زیر باشد:
۱- دادهها در این سیستم به صورت رابطهای (جدولی) نمیباشند
۲-دادهها به صورت توزیع شده نگهداری میشوند.
۳-سیستم نرمافزاری متن باز میباشد.
۴-پایگاه داده مقیاس پذیر به صورت افقی میباشد(در مطالب بعدی توضیح داده خواهد شد.)
همانگونه که گفته شد این نوع پایگاه داده به منظور رفع نیازهای برنامههای با حجم ورود و خروج داده بسیار بالا (برنامههای مدرن وب فعلی) ایجاد شدند.
شروع کار پیادهسازی این سیستمها در اوایل سال ۲۰۰۹ شکل گرفت و با سرعت زیادی رشد کرد و همچنین ویژگیهای کلی دیگری نیز به این نوع سیستم اضافه شد.
که این ویژگیها عبارتند از:
جهت پیاده سازی پایگاه داده با این سیستمها تا حدودی نگرش کلی به دادهها و نحوهی چیدمان آنها تغییر میکند ، به صورت کلی مباحث مربوط به normalization و de-normalization و تصور دادهها به صورت جدولی کنار میرود.
سیستم NoSql به جهت دستهبندی نحوهی ذخیرهسازی دادهها و ارتباط بین آنها به ۴ دسته کلی تقسیم میشود که معرفی کلی آن دستهبندیها موضوع مطلب بعدی میباشد.
با فراگیر شدن اینترنت در سالهای اخیر و افزایش کاربران ، سیستمهای RDBMS جوابگوی نیازهای برنامهنویسان در حوزهی وب نبودند زیرا نیاز به نگهداری دادهها با حجم بالا و سرعت خواندن و نوشتن بالا از جمله نقط ضعف سیستمهای RDBMS میباشد ، چرا که با افزایش شدید کاربران دادهها اصولا به صورت منطقی ساختار یکدست خود را جهت نگهداری از دست میدهند و به این ترتیب عملیات نرمال سازی منجر به ساخت جداول زیادی میشود که نتیجه آن برای هر کوئری عملیات Joinهای متعدد میباشد که سرعت خواندن و نوشتن را به خصوص برای برنامههای با گسترهی وب پایین میآورد و مشکلات دیگری در سیستمهای RDBMS که ویژگیهای سیستمهای NoSql مشخص کننده آن مشکلات است که در ادامه به آن میپردازیم.
طبق تعریف کلی پایگاه داده NOSql عبارت است از:
نسل بعدی پایگاه داده (نسل از بعد RDBMS ) که اصولا دارای چند ویژگی زیر باشد:
۱- دادهها در این سیستم به صورت رابطهای (جدولی) نمیباشند
۲-دادهها به صورت توزیع شده نگهداری میشوند.
۳-سیستم نرمافزاری متن باز میباشد.
۴-پایگاه داده مقیاس پذیر به صورت افقی میباشد(در مطالب بعدی توضیح داده خواهد شد.)
همانگونه که گفته شد این نوع پایگاه داده به منظور رفع نیازهای برنامههای با حجم ورود و خروج داده بسیار بالا (برنامههای مدرن وب فعلی) ایجاد شدند.
شروع کار پیادهسازی این سیستمها در اوایل سال ۲۰۰۹ شکل گرفت و با سرعت زیادی رشد کرد و همچنین ویژگیهای کلی دیگری نیز به این نوع سیستم اضافه شد.
که این ویژگیها عبارتند از:
- Schema-free
: بدون شَما ! ، با توجه به برنامههای وبی فعلی ممکن است شمای نگهداری
دادهها ( ساختار کلی ) مرتبا و یا گهگاهی تغییر کند. لذا در این سیستمها
اصولا دادهها بدون شمای اولیه طراحی و ذخیره میشوند. ( به عنوان مثال
میتوان در یک سیستم که مشخصات کاربران وارد سیستم میشود برای یک کاربر یک
سری اطلاعات اضافی و برای کاربری دیگر از ورود اطلاعات اضافی صرفنظر کرد ،
و در مقایسه با RDBMS به این ترتیب از ورود مقادیر Null و یا پیوندهای
بیمورد جلوگیری کرد.
کنترل اطلاعات الزامی توسط لایه سرویس برنامه انجام میشود. ( در زبان جاوا توسط jsr-303 و یاBean Validation ها) - easy replication support : در این سیستم ، نحوهی گرفتن نسخههای پشتیبان و sync بودن نسخههای مختلف بسیار ساده و سر راست میباشد و سرور پایگاه داده به محض عدم توانایی خواندن و یا نوشتن از روی دیسک سراغ نسخهی پشتیبان میرود و آن نسخه را به عنوان نسخهی اصلی در نظر میگیرد.
- Simple API : به دلیل متنباز بودن و فعال بودن Community این سیستمها APIهای ساده و بهینهای برای اکثر زبانهای برنامهنویس محبوب ایجاد شده است که در پستهای بعدی با ارائه مثال آنها را بررسی خواهیم کرد.
- eventually consistent : در سیستمهای RDBMS که دادهها خاصیت ACID را ( در قالب Transaction) پیاده میکنند ، در این سیستمهای دادهها در وضعیت BASE قرار دارند که سرنام کلمات Basically Available ، Soft State ، Eventual Consistency میباشد.
- huge amount of data: این سیستمها به منظور کار با دادههای با حجم بالا ایجاد شدهاند ، یک تعریف کلی میگوید اگر مقدار دادههای نگهداری شده در پایگاههای داده برنامه شما ظرفیتی کمتر از یک ترابایت داده دارد از پایگاه داده RDBMS استفاده کنید واگر ظرفیت آن از واحد ترابایت فراتر میرود از سیستمهای NOSql استفاده کنید.
جهت پیاده سازی پایگاه داده با این سیستمها تا حدودی نگرش کلی به دادهها و نحوهی چیدمان آنها تغییر میکند ، به صورت کلی مباحث مربوط به normalization و de-normalization و تصور دادهها به صورت جدولی کنار میرود.
سیستم NoSql به جهت دستهبندی نحوهی ذخیرهسازی دادهها و ارتباط بین آنها به ۴ دسته کلی تقسیم میشود که معرفی کلی آن دستهبندیها موضوع مطلب بعدی میباشد.
نظرات مطالب
معماری میکروسرویسها
من در مورد همه مشکلات میکرو سرویس زیاد با شما موافق نیستم
- از آنجایی که ارتباط بین سرویسها در بستر شبکه انجام میشود، انتظار کندی عملکرد سرویسها دور از ذهن نیست. (اتفاقا بخاطر توزیع برنامه بر روی چند سیستم در زمانی که بار زیادی بر روی سیستم هست پاسخ گویی به کاربر میتونه خیلی بسرعت انجام بپذیره و اتفاقا یکی از مزایای اون هست)
- به دلیل ارتباطات شبکهای، احتمال آسیب پذیریهای امنیتی در این نوع برنامهها بیشتر است. (البته بیشتر این توزیع در server farm انجام میشه ،یعنی پشت فایروال و کسی جز سرورها در این شبکه خصوصی وجود ندارد، نمیگم نیست ولی خیلی نیست)
- نوشتن سرویسهایی که در بستر شبکه با سایر سرویسها در ارتباط هستند سختی و مشکلات خود را دارد. برنامهنویس در این شرایط، درگیر برقراری ارتباط، رمزگذاری دادهها در صورت نیاز و تبدیل آنها میشود.(همان موارد بالا)
- به دلیل مجزا بودن بخشهای مختلف برنامه، مانیتور کردن و ردیابی عملکرد سرویسها، یکی از کارهای اصلی توسعه دهنده یا استفاده کننده از برنامه است. (اینم خودش یک فایده است و طبق اصل SRP و تفاوت MicroServic با SOA بیشتر بر همین نکته تاکید داره که یک میکرو سرویس کاملا مستقل میباشد و راحتتر قابل مانیتور کردن و ردیابی عملکرد سرویس میباشد
- در مجموع سرعت برنامههای نوشته شده با معماری Microservices کندتر از برنامههای نوشته شده با معماری Monolithic است. دلیل آن محیط اجرایی برنامهها است. برنامههایی با معماری Monolithic بر روی حافظه سرور پردازش میشوند. (باز تاکید که اصل استفاده از میکرو سرویس برای سیستم هایی با تراکنش بالا میباشد ،هدف توسعه راحتر و بدون تاثیر بر بقیه سرویسها و حتی بدون توقف آنها میباشد، همچنین امکان horizontal Scalability نرم افزار و بالا بردن تعداد سرورهای ارائه دهنده سرویس براحتی بوجود خواهد امد ، پس میتونه سرعت رو خیلی بالا ببره و مشکل توقف سرویس که در خیلی از سامانههای ایرانی میبینیم رو از بین میبره )
بسیار عالی بود . تنها یک مشکل برای من در ارتباط با کدهای آموزشی که برای استفاده از لوسین در اینترنت پیدا کردم وجود داره و اون هم اینکه در اونها کلاس و توابع به صورت استاتیک تعریف و در کنترلرها و یا کلاسهای لایه سرویس فراخوانی شدن .
این مسئله باعث اشکال در نوشتن آزمون واحد برای کنترلرها و یا متدها نمیشه ؟ آیا در استاتیک معرفی کردن کلاس و توابع علت و مزیت خاصی وجود داره ؟