Redis Fundamentals for .NET Developers
Redis is an open source, in-memory data store used by millions of developers as a database, cache, streaming engine, and even a message broker.
In this live sessions, Stephen Lorello, Senior Field Engineer at Redis, joins us to show the the fundamental features .NET developers show know about using Redis
تغییر مجوز ImageSharp به AGPL
ImageSharp, ImageSharp.Drawing, and ImageSharp.Web will all be dual licensed under a AGPLv3/Commercial license. The AGPLv3 license will come with exceptions which allow bundling the code alongside all well known open source licenses (Apache 2.0, MIT etc). Any projects seen as direct competition (Imaging SDKs) will not be able to utilize that exception.
افزونه نمایش فرمت Json در گوگل کروم
Makes JSON easy to read. Open source.
FEATURES
• JSON & JSONP support
• Syntax highlighting
• Collapsible trees, with indent guides
• Clickable URLs
• Toggle between raw and parsed JSON
• Works on any valid JSON page – URL doesn't matter
• Works on local files too (if you enable this in chrome://extensions)
• You can inspect the JSON by typing "json" in the console
OpenAPI (f.k.a Swagger) Specification code generator. Supports C#, Go, Java, Node.js, TypeScript, Python, Ruby and PHP.
AutoRest is an open source tool that generates client libraries for accessing RESTful web services.
Video Tutorial : https://azure.microsoft.com/en-us/resources/videos/inside-autorest-with-david-justice/
JET یک فریم ورک SPA از اوراکل
الف) Key-Value stores که پایه بانکهای اطلاعاتی NoSQL را تشکیل داده و اهدافی عمومی را دنبال میکنند.
ب) Wide column stores که در شرکتهای بزرگ اینترنتی بیشتر مورد استفاده قرار گرفتهاند.
ج) Document stores یا بانکهای اطلاعاتی NoSQL سندگرا.
د) Graph databases که بیشتر برای ردیابی ارتباطات بین موجودیتها بکار میروند.
و در تمام این گروهها، مکانیزمهای Key-Value به شدت مورد استفادهاند.
الف) Key-Value stores
Key-Value stores یکی از عمومیترین و پایهایترین گروههای بانکهای اطلاعاتی NoSQL را تشکیل میدهند. البته این مورد بدین معنا نیست که این رده، جزو محبوبترینها نیز بهشمار میروند.
این نوع بانکهای اطلاعاتی شامل جداولی از اطلاعات هستند. هر جدول نیز شامل تعدادی ردیف است؛ چیزی همانند بانکهای اطلاعاتی رابطهای. اما در هر ردیف، یک Dictionary یا آرایهای از اطلاعات key-value شکل را شاهد خواهید بود. در اینجا ساختار و اسکیمای ردیفها میتوانند نسبت به یکدیگر کاملا متفاوت باشند (دید لیبرال نسبت به اسکیما، که در قسمت قبل به آن پرداخته شد). در این بین، تنها تضمین خواهد شد که هر ردیف، Id منحصربفردی دارد.
از این نوع بانکهای اطلاعاتی، در سکوهای کاری ابری زیاد استفاده میشود. دو مثال مهم در اینباره شامل Amazon SimpleDB و Azure Table Storage هستند.
سایر نمونههای مهم دیگری از بانکهای اطلاعاتی NoSQL که بر مبنای مفهوم Key-Value stores کار میکنند، عبارتند از MemcacheDB و Voldemort. به علاوه در Amazon web services بانک اطلاعاتی دیگری به نام DynamoDB به عنوان یک سرویس عمومی در دسترس است. همچنین Dynomite نیز به عنوان نمونه سورس باز Dynamo مطرح است.
Redis و Riak نیز جزو بانکهای اطلاعاتی Key-Value store بسیار معروف بهشمار میروند.
همانطور که در تصویر فوق ملاحظه میکنید، Key-Value stores دارای بانکهای اطلاعاتی شامل جداول مختلف هستند. در اینجا همچنین ساختار ردیفهایی از اطلاعات این جداول نیز مشخص شدهاند. هر ردیف، یک کلید دارد به همراه تعدادی جفت کلید-مقدار. در این جداول، اسکیما ثابت نگه داشته شده است و از ردیفی به ردیف دیگر متفاوت نیست؛ اما این مساله اختیاری است. برای مثال میتوان در ردیف اطلاعات یک مشتری خاص، کلید-مقدارهایی خاص او را نیز درج کرد که لزوما در سایر ردیفها، نیازی به وجود آنها نیست.
به علاوه باید به خاطر داشت که هرچند به ظاهر last_orderها به شماره Id سفارشات مرتبط هستند، اما مفاهیمی مانند کلیدهای خارجی بانکهای اطلاعاتی رابطهای، در اینجا وجود خارجی ندارند. بیشتر در اینجا هدف سهولت جستجوی اطلاعات است.
ب) Wide column stores
Wide column stores دارای جداولی است که درون آنها ستونهایی قابل تعریف است. درون این ستونها که یادآور بانکهای اطلاعاتی رابطهای هستند، اطلاعات به شکل key-value با ساختاری متفاوت، قابل ذخیره سازی هستند. در اینجا هر ستون، میتواند شامل گروهی از ستونها که بر اساس مفاهیم جفتهای key-value کار میکنند، باشد.
این نوع بانکهای اطلاعاتی عموما در سایتهای اینترنتی بسیار بزرگ و برنامههای «Big data» استفاده میشوند. برای مثال:
- BigTable گوگل که یک محصول اختصاصی و غیرعمومی است؛ اما جزئیات آن را به عنوان مقالات علمی منتشر کرده است.
- دنیای سورس باز به رهبری Yahoo، نمونه سورس باز BigTable را به نام Hbase ارائه داده است.
- در فیس بوک، از بانک اطلاعاتی دیگری به نام Cassandra استفاده میکنند. در اینجا به گروهی از ستونها super columns و جداول super column families گفته میشود.
در اینجا نیز جداول و ردیفها وجود دارند و هر ستون باید عضوی از خانواده یک super column باشد. ساختار ردیفها در این تصویر یکسان درنظر گرفته شدهاند، اما اگر نیاز بود، برای مثال میتوان در ردیفی خاص، ساختار را تغییر داد و مثلا middle name را نیز بر اساس نیاز، به ردیفی اضافه کرد.
ج) Document stores
Document stores بجای جداول، دارای بانکهای اطلاعاتی مختلفی هستند و در اینجا بجای ردیفها، سند یا document دارند. ساختار سندها نیز عموما بر مبنای اشیاء JSON تعریف میگردد (که البته این مورد الزامی نبوده و از هر محصول، به محصول دیگری ممکن است متفاوت باشد؛ اما عمومیت دارد). بنابراین هر سند دارای تعدادی خاصیت است (چون اشیاء JSON به این نحو تعریف میگردند) که دارای مقدار هستند. در نگاه اول، شاید این نوع اسناد، بسیار شبیه به key-value stores به نظر برسند. اما در حین تعریف اشیاء JSON، یک مقدار میتواند خود یک شیء کامل دیگر باشد و نه صرفا یک مقدار ساده. به همین جهت عدهای به این نوع بانکهای اطلاعاتی، بانکهای اطلاعاتی Key-value store سفارشی و خاص نیز میگویند.
این نوع ساختار منعطف، برای ذخیره سازی اطلاعات اشیاء تو در تو و درختی بسیار مناسب است. همچنین این اسناد میتوانند حاوی پیوستهایی نیز باشد؛ مانند پیوست یک فایل به یک سند.
در Document stores، نگارشهای قدیمی اسناد نیز نگهداری میگردند. به همین جهت این نوع بانکهای اطلاعاتی برای ایجاد برنامههای مدیریت محتوا نیز بسیار مطلوب میباشند.
با توجه به مزایایی که برای این رده از بانکهای اطلاعاتی NoSQL ذکر گردید، Document stores در بین برنامه نویسها بسیار محبوب و پرکاربرد هستند.
از این دست بانکهای اطلاعاتی NoSQL، میتوان به CouchDB ، MongoDB و RavenDB اشاره کرد.
سایر مزایای Document stores که به پرکاربرد شدن آنها کمک کردهاند به شرح زیر هستند:
- هر سند را میتوان با یک URI آدرس دهی کرد.
- برای نمونه CouchDB از یک full REST interface برای دسترسی و کار با اسناد پشتیبانی میکند (چیزی شبیه به ASP.NET WEB API در دات نت). در اینجا با استفاده از یک وب سرور توکار و بکارگیری HTTP Verbs مانند Put، Delete، Get و غیره، امکان کار با اسناد وجود دارد.
- اغلب بانکهای اطلاعاتی Document stores از JavaScript به عنوان native language خود بهره میبرند (جهت سهولت کار با اشیاء JSON).
در اینجا دو دیتابیس، بجای دو جدول وجود دارند. همچنین در مقایسه با بانکهای اطلاعاتی key-value، برای نمونه، مقدار خاصیت آدرس، خود یک شیء است که از دو خاصیت تشکیل شده است. به علاوه هر خاصیت Most_Recent یک Order، به سند دیگری در بانک اطلاعاتی Orders لینک شده است.
د) Graph databases
Graph databases نوع خاصی از بانکهای اطلاعاتی NoSQL هستند که جهت ردیابی ارتباطات بین اطلاعات طراحی شدهاند و برای برنامههای شبکههای اجتماعی بسیار مفید هستند.
در واژه نامه این بانکهای اطلاعاتی Nodes و Edges (اتصال دهندههای نودها) تعریف شدهاند. در اینجا نودها میتوانند دارای خاصیتها و مقادیر متناظر با آنها باشند.
یکی از معروفترین Graph databases مورد استفاده، Neo4j نام دارد.
در اینجا یک شخص را که دارای رابطه آدرس با شیء آدرس ذکر شده است را مشاهده میکنید. همچنین این شخص دارای رابطه دوستی با سه شخص دیگر است.
context.MapRouteLowercase( "Admin_default2", "Admin/Post/Manage/{page}", new { controller = "Post", action = "Manage", page = UrlParameter.Optional } );
مشخص سازی رشتههای متفاوت اتصالی
فرض کنید برنامهی جاری شما قرار است از دو بانک اطلاعاتی مشخص استفاده کند که تعاریف رشتههای اتصالی آنها در وب کانفیگ به صورت ذیل مشخص شدهاند:
<connectionStrings> <clear /> <add name="Sample07Context" connectionString="Data Source=(local);Initial Catalog=TestDbIoC;Integrated Security = true" providerName="System.Data.SqlClient" /> <add name="Database2012" connectionString="Data Source=(local);Initial Catalog=testdb2012;Integrated Security = true" providerName="System.Data.SqlClient" /> </connectionStrings>
تغییر Context برنامه جهت پذیرش رشتههای اتصالی پویای قابل تغییر در زمان اجرا
اکنون که قرار است کاربران در حین ورود به برنامه، بانک اطلاعاتی مدنظر خود را انتخاب کنند و یا سیستم قرار است به ازای کاربری خاص، رشتهی اتصالی خاص او را به Context ارسال کند، نیاز است Context برنامه را به صورت ذیل تغییر دهیم:
using System.Collections.Generic; using System.Data.Entity; using System.Linq; using EF_Sample07.DomainClasses; namespace EF_Sample07.DataLayer.Context { public class Sample07Context : DbContext, IUnitOfWork { public DbSet<Category> Categories { set; get; } public DbSet<Product> Products { set; get; } /// <summary> /// It looks for a connection string named Sample07Context in the web.config file. /// </summary> public Sample07Context() : base("Sample07Context") { } /// <summary> /// To change the connection string at runtime. See the SmObjectFactory class for more info. /// </summary> public Sample07Context(string connectionString) : base(connectionString) { //Note: defaultConnectionFactory in the web.config file should be set. } public void SetConnectionString(string connectionString) { this.Database.Connection.ConnectionString = connectionString; } } }
یک متد دیگر هم در اینجا در انتهای کلاس به نام SetConnectionString تعریف شدهاست. از این متد در حین ورود کاربر به سایت میتوان استفاده کرد. برای مثال حداقل دو نوع طراحی را میتوان درنظر گرفت:
الف) کاربر با برنامهای کار میکند که به ازای سالهای مختلف، بانکهای اطلاعاتی مختلفی دارد و در ابتدای ورود، یک drop down انتخاب سال کاری برای او درنظر گرفته شدهاست (علاوه بر سایر ورودیهای استانداردی مانند نام کاربری و کلمهی عبور). در این حالت بهتر است متد SetConnectionString نام رشتهی اتصالی را بر اساس سال انتخابی، در حین لاگین دریافت کند که اطلاعات آن در فایل کانفیگ سایت پیشتر مشخص شدهاست.
ب) کاربر یا مشتری پس از ورود به سایت، نیاز است صرفا از بانک اطلاعاتی خاص خودش استفاده کند. بنابراین اطلاعات تعریف کاربران و مشتریها در یک بانک اطلاعاتی مجزا قرار دارند و پس از لاگین، نیاز است رشتهی اتصالی او به صورت پویا از بانک اطلاعاتی خوانده شده و سپس توسط متد SetConnectionString تنظیم گردد.
مدیریت سشنهای رشتهی اتصالی جاری
پس از اینکه کاربر، در حین ورود مشخص کرد که از چه بانک اطلاعاتی قرار است استفاده کند و یا اینکه برنامه بر اساس اطلاعات ثبت شدهی او تصمیمگیری کرد که باید از کدام رشتهی اتصالی استفاده کند، نگهداری این رشتهی اتصالی نیاز به سشن دارد تا به ازای هر کاربر متصل به سایت منحصربفرد باشد. در مورد مدیریت سشنها در برنامههای وب، از نکات مطرح شدهی در مطلب «مدیریت سشنها در برنامههای وب به کمک تزریق وابستگیها» استفاده خواهیم کرد:
using System; using System.Threading; using System.Web; using EF_Sample07.DataLayer.Context; using EF_Sample07.ServiceLayer; using StructureMap; using StructureMap.Web; using StructureMap.Web.Pipeline; namespace EF_Sample07.IoCConfig { public static class SmObjectFactory { private static readonly Lazy<Container> _containerBuilder = new Lazy<Container>(defaultContainer, LazyThreadSafetyMode.ExecutionAndPublication); public static IContainer Container { get { return _containerBuilder.Value; } } public static void HttpContextDisposeAndClearAll() { HttpContextLifecycle.DisposeAndClearAll(); } private static Container defaultContainer() { return new Container(ioc => { // session manager setup ioc.For<ISessionProvider>().Use<DefaultWebSessionProvider>(); ioc.For<HttpSessionStateBase>() .Use(ctx => new HttpSessionStateWrapper(HttpContext.Current.Session)); ioc.For<IUnitOfWork>() .HybridHttpOrThreadLocalScoped() .Use<Sample07Context>() // Remove these 2 lines if you want to use a connection string named Sample07Context, defined in the web.config file. .Ctor<string>("connectionString") .Is(ctx => getCurrentConnectionString(ctx)); ioc.For<ICategoryService>().Use<EfCategoryService>(); ioc.For<IProductService>().Use<EfProductService>(); ioc.For<ICategoryService>().Use<EfCategoryService>(); ioc.For<IProductService>().Use<EfProductService>(); ioc.Policies.SetAllProperties(properties => { properties.OfType<IUnitOfWork>(); properties.OfType<ICategoryService>(); properties.OfType<IProductService>(); properties.OfType<ISessionProvider>(); }); }); } private static string getCurrentConnectionString(IContext ctx) { if (HttpContext.Current != null) { // this is a web application var sessionProvider = ctx.GetInstance<ISessionProvider>(); var connectionString = sessionProvider.Get<string>("CurrentConnectionString"); if (string.IsNullOrWhiteSpace(connectionString)) { // It's a default connectionString. connectionString = "Database2012"; // this session value should be set during the login phase sessionProvider.Store("CurrentConnectionStringName", connectionString); } return connectionString; } else { // this is a desktop application, so you can store this value in a global static variable. return "Database2012"; } } } }
نکتهی مهم این تنظیمات، قسمت مقدار دهی سازندهی کلاس Context برنامه به صورت پویا توسط IoC Container جاری است. در اینجا هر زمانیکه قرار است وهلهای از Sample07Context ساخته شود، از سازندهی دوم آن که دارای پارامتری به نام connectionString است، استفاده خواهد شد. همچنین مقدار آن به صورت پویا از متد getCurrentConnectionString که در انتهای کلاس تعریف شدهاست، دریافت میگردد.
در این متد ابتدا مقدار HttpContext.Current بررسی شدهاست. این مقدار اگر نال باشد، یعنی برنامهی جاری یک برنامهی دسکتاپ است و مدیریت رشتهی اتصالی جاری آنرا توسط یک خاصیت Static یا Singleton تعریف شدهی در برنامه نیز میتوان تامین کرد. از این جهت که در هر زمان، تنها یک کاربر در App Domain جاری برنامهی دسکتاپ میتواند وجود داشته باشد و Singleton یا Static تعریف شدن اطلاعات رشتهی اتصالی، مشکلی را ایجاد نمیکند. اما در برنامههای وب، چندین کاربر در یک App Domain به سیستم وارد میشوند. به همین جهت است که مشاهده میکنید در اینجا از تامین کنندهی سشن، برای نگهداری اطلاعات رشتهی اتصالی جاری کمک گرفته شدهاست.
کلید این سشن نیز در این مثال مساوی CurrentConnectionStringName تعریف شدهاست. بنابراین در حین لاگین موفقیت آمیز کاربر، دو مرحلهی زیر باید طی شوند:
sessionProvider.Store("CurrentConnectionString", "Sample07Context"); uow.SetConnectionString(WebConfigurationManager.ConnectionStrings[_sessionProvider.Get<string>("CurrentConnectionString")].ConnectionString);
سپس از متد SetConnectionString برای خواندن مقدار نام مشخص شده در سشن CurrentConnectionStringName کمک گرفتهایم. هرچند سازندهی کلاس Context برنامه، هر دو حالت استفاده از نام رشتهی اتصالی و یا مقدار کامل رشتهی اتصالی را پشتیبانی میکند، اما خاصیت this.Database.Connection.ConnectionString تنها رشتهی کامل اتصالی را میپذیرد (بکار رفته در متد SetConnectionString).
تا اینجا کار پویا سازی انتخاب و استفاده از رشتهی اتصالی برنامه به پایان میرسد. هر زمانیکه قرار است Context برنامه توسط IoC Container نمونه سازی شود، به متد getCurrentConnectionString رجوع کرده و مقدار رشتهی اتصالی را از سشن تنظیم شدهای به نام CurrentConnectionStringName دریافت میکند. سپس از مقدار آن جهت مقدار دهی سازندهی دوم کلاس Context استفاده خواهد کرد.
مدیریت migrations خودکار برنامه در حالت استفاده از چندین بانک اطلاعاتی
یکی از مشکلات کار با برنامههای چند دیتابیسی، به روز رسانی ساختار تمام بانکهای اطلاعاتی مورد استفاده، پس از تغییری در ساختار مدلهای برنامه است. از این جهت که اگر تمام بانکهای اطلاعاتی به روز نشوند، کوئریهای جدید برنامه که از خواص و فیلدهای جدید استفاده میکنند، دیگر کار نخواهند کرد. پویا سازی اعمال این تغییرات را میتوان به صورت ذیل انجام داد:
using System; using System.Data.Entity; using System.Web; using EF_Sample07.DataLayer.Context; using EF_Sample07.IoCConfig; namespace EF_Sample07.WebFormsAppSample { public class Global : HttpApplication { void Application_Start(object sender, EventArgs e) { initDatabases(); } private static void initDatabases() { // defined in web.config string[] connectionStringNames = { "Sample07Context", "Database2012" }; foreach (var connectionStringName in connectionStringNames) { Database.SetInitializer( new MigrateDatabaseToLatestVersion<Sample07Context, Configuration>(connectionStringName)); using (var ctx = new Sample07Context(connectionStringName)) { ctx.Database.Initialize(force: true); } } } void Application_EndRequest(object sender, EventArgs e) { SmObjectFactory.HttpContextDisposeAndClearAll(); } } }
در این مثال خاص، متد initDatabases در حین آغاز برنامه فراخوانی شدهاست. منظور این است که اینکار در طول عمر برنامه تنها کافی است یکبار انجام شود و پس از آن است که EF Code first میتواند از رشتههای اتصالی متفاوتی که به آن ارسال میشود، بدون مشکل استفاده کند. زیرا اطلاعات نگاشت کلاسهای مدل برنامه به جداول بانک اطلاعاتی به این ترتیب است که کش میشوند و یا بر اساس کلاس Configuration به صورت خودکار به بانک اطلاعاتی اعمال میگردند.
کدهای کامل این مثال را که در حقیقت نمونهی بهبود یافتهی مطلب «EF Code First #12» است، از اینجا میتوانید دریافت کنید:
UoW-Sample