ممنون از مطلب مفیدتون . جالب اینه که بدون هیچ دردسری از خواص راهبری میشه برای به روز رسانی و افزودن رکوردهای مرتبط در صورت وجود رابطههای صحیح و نرمال سازی دقیق پایگاه داده بهترین استفاده رو کرد ... واقعا ORMها برنامه نویسارو از شر کد نویسی تکراری و خسته کنندهی بانک اطلاعاتی تا حد زیادی راحت کردن ...
نظرات اشتراکها
کرهجنوبی و ژاپن رکورددار بیشترین سرعت اینترنت در جهان
سرعت بیشتر؟! من از داتک اینترنت گرفتم. سه ماهه با 5 گیگ حجم اولیه. قبلا (تا یک ماه قبل) از ساعت 1 بامداد تا 7 صبح آن رایگان بود (در محاسبه حجم حساب نمیشد). الان یک ماه هست بدون اطلاع به کاربران، این ساعت شده از 2 بامداد تا 7 صبح. چون اطلاع نداشتم، مثل قبل از ساعت 1 بامداد هر شب دانلود میکردم. چند روز قبل دیدم که حجم 5 گیگ اولیهام زودتر از موعد تمام شده! تبدیل این مساله به 2 بامداد، تقریبا زندگی من رو مختل کرده.
مطالب
خواندنیهای 17 مرداد
اس کیوال سرور
اس کیوال لایت
توسعه وب
دات نت فریم ورک
دلفی
سی و مشتقات
متفرقه
محیطهای مجتمع توسعه
مسایل انسانی، اجتماعی و مدیریتی برنامه نویسی
ویندوز
نظرات مطالب
Globalization در ASP.NET MVC - قسمت ششم
دلیل خاصی برای تفکیک این چنینی وجود نداره و همونطور که دوستمون گفتن این روشی که شما اشاره کردین مشکلات و معایبی هم به همراه داره.
روش اشاره شده تو این مطلب تو بیش از 99 درصد پروژهها کفایت میکنه. فقط تو پروژههای بسیار بسیار بزرگ با ورودیهای منابع بسیار بسیار زیاد (چند صد هزار و یا بیشتر) تغییر این ساختار برای رسیدن به کارایی مناسب میتونه مفید باشه.
درهرصورت اگر نیاز به تغییر ساختار جدول دارین فقط لایه دسترسی به بانک باید تغییر بکنه و فرایند کلی دسترسی به ورودیهای منابع ذخیره شده در دیتابیس باید به همون صورتی باشه که در اینجا آورده شده. یعنی درنهایت با استفاده از سه پارامتر نام منبع، نام کالچر و عنوان کلید درخواستی کار استخراج مقدار ورودی باید انجام بشه.
نوع دیگری از کوئریهای پرکاربرد، کوئریهای مرتبط با ثبت، حذف و ویرایش اطلاعات هستند که در این قسمت آنها را بررسی میکنیم. البته این مثالها از یکسری مثال کوئریهای مرتبط با PostgreSQL، به EF-Core تبدیل و ترجمه شدهاند. به همین جهت تطابق یک به یکی در اینجا وجود نداشته و روش شیءگرایی که ORMها برای کار با دادهها بکار میگیرند، الزاما کوئریهای یکسانی را تولید نمیکنند؛ اما نتیجهی نهایی آنها یکی است.
مثال 1: افزودن ردیفی به یک جدول بانک اطلاعاتی
امکان و ویژگی جدیدی به نام SPA قرار است به مجموعه اضافه شود. اطلاعات آن که شامل موارد ذیل است، نیاز است به جدول facilities اضافه شود:
اگر قرار باشد چنین کاری را توسط دستورات SQL انجام دهیم، عموما به یکی از دو روش زیر عمل میشود:
که معادل آن در EF-Core به صورت زیر است:
ابتدا وهلهای از موجودیت Facility به DbSet مرتبط با آن اضافه میشود و در آخر SaveChanges فراخوانی خواهد شد تا کوئری متناظر با آن ساخته شده و به بانک اطلاعاتی اعمال شود.
مثال 2: افزودن چندین ردیف از اطلاعات به یک جدول بانک اطلاعاتی
همان مثال قبلی را درنظر بگیرید. اینبار میخواهیم دو ردیف را به آن اضافه کنیم:
معادل کدهای SQL چنین عملی، میتواند کوئری زیر باشد:
و روش انجام آن در EF-Core تفاوتی با مثال قبلی ندارد:
در اینجا میتوان به هر تعدادی که نیاز است وهلههای جدیدی از Facility را به context افزودن و سپس SaveChanges را در آخر کار فراخوانی کرد. اینکه EF-Core دستورات insert معادل را به یکباره و یا به صورت مجزایی اجرا میکند، به مفهومی به نام batching مرتبط است. اطلاعات بیشتر
مثال 3: افزودن اطلاعات محاسبه شده به یک جدول بانک اطلاعاتی
اطلاعات زیر را درنظر بگیرید:
در مثال اصلی عنوان شده که میخواهیم ID آنرا یکی بیشتر از ردیف قبلی ثبت کنیم. در EF-Core و تنظیمات موجودیتهایی که داریم:
چون ستون ID به صورت خود افزایش یابنده معرفی شدهاست که از صفر شروع میشود و به صورت خودکار توسط بانک اطلاعاتی یکی یکی افزایش مییابد، نیازی به حل این مساله وجود ندارد. چون ID افزایش یابنده را خود بانک اطلاعاتی محاسبه میکند. همچنین به همین علت در مثالهای قبلی نیز ID را به صورت مستقیمی مقدار دهی نکردیم. اگر نیاز به انجام چنین کاری وجود داشته باشد (ذکر صریح ID خاصی)، با توجه به طراحی بانک اطلاعاتی حاصل از این تنظیمات:
باید مانند مثال ثبت اطلاعات اولیهی در بانک اطلاعاتی در قسمت اول این سری، از روش SET IDENTITY_INSERT Facilities ON استفاده کرد تا بتوان مجوز ثبت دستی این ID کنترل شدهی توسط بانک اطلاعاتی را پیدا کرد.
مثال 4: به روز رسانی اطلاعاتی از پیش موجود
میخواهیم مقدار InitialOutlay دومین زمین تنیس را از 8000 موجود به 10000 تغییر دهیم. با توجه به اینکه ID این زمین شماره 1 است، در حالت متداول SQL نویسی، به کدهای زیر خواهیم رسید:
که معادل EF-Core آن به صورت زیر است:
این دستورات کوئری مشابهی را تولید نمیکنند. ابتدا موجودیت متناظر با ID شمارهی 1 از بانک اطلاعاتی واکشی شده و سپس مقدار خاصیتی از آن تغییر کردهاست. در آخر SaveChanges بر روی آن فراخوانی میشود.
EF-Core برای اینکه بتواند تغییرات اعمالی به یک شیء را محاسبه کند، نیاز دارد تا آن شیء را به نحوی در سیستم change tracking خودش موجود داشته باشد. هر نوع کوئری که در EF-Core نوشته میشود و به همراه متد AsNoTracking نیست، خروجی تک تک اشیاء حاصل از آن پیش از ارائهی نهایی، وارد سیستم change tracking آن میشوند. یعنی اگر مقادیر خواص این اشیاء را تغییر داده و بر روی آنها SaveChanges را فراخوانی کنیم، کوئریهای متناظر با به روز رسانی تنها این خواص تغییر یافته به صورت خودکار محاسبه شده و به بانک اطلاعاتی اعمال میشوند.
فراخوانی متد AsNoTracking بر روی کوئریهای EF-Core، تولید پروکسیهای change tracking را غیرفعال میکند. یک چنین کوئریهایی صرفا کاربردهای گزارشگیری فقط خواندنی را دارند و نسبت به کوئریهای معمولی، سریعتر و با مصرف حافظهی کمتری هستند. بنابراین نتایج حاصل از کوئریهای متداول EF-Core، به صورت پیشفرض (یعنی بدون داشتن متد AsNoTracking) هم خواندنی و هم نوشتنی با قابلیت اعمال به بانک اطلاعاتی هستند.
مثال 5: به روز رسانی چندین ردیف و چندین جدول در یک زمان
میخواهیم مقادیر MemberCost و GuestCost دو زمین تنیس را به 6 و 30 تغییر دهیم. روش انجام اینکار با SQL نویسی معمولی به صورت زیر است:
اما همانطور که عنوان شد در EF-Core ابتدا باید اشیاء متناظر با این زمینهای تنیس را در سیستم change tacking موجود داشت و سپس نسبت به ویرایش آنها اقدام نمود. یکی از روشهای وارد کردن اشیاء به سیستم change tacking، نوشتن کوئریهای بدون متد AsNoTracking است و سپس به روز رسانی نتایج حاصل از آنها که اکنون توسط پروکسیهای change tracking محصور شدهاند و در آخر فراخوانی SaveChanges بر روی context جاری:
مثال 6: به روز رسانی اطلاعات یک ردیف بر اساس اطلاعات ردیفی دیگر
میخواهیم هزینهی دومین زمین تنیس را به نحوی ویرایش کنیم که 10 درصد بیشتر از هزینهی اولین زمین تنیس باشد.
روش پیشنهادی انجام اینکار با SQL نویسی مستقیم به صورت زیر است:
در EF-Core میتوان اشیاء متناظر با این دو زمین تنیس را ابتدا واکشی کرد، سپس تغییر داد و در نهایت ذخیره کرد:
مثال 7: حذف تمام اطلاعات یک جدول
میخواهیم تمام اطلاعات جدول bookings را حذف کنیم.
روش انجام اینکار با SQL نویسی مستقیم به صورت زیر است:
اما ... این تک کوئری، معادلی را در EF-Core استاندارد ندارد. چون EF-Core نیاز دارد مدام تمام اطلاعات ویرایشی/حذف و به روز رسانی را در context و سیستم change tracking خودش داشته باشد، ابتدا باید توسط یک کوئری لیست اشیاء مدنظر را تهیه کرد و سپس آنرا به متد RemoveRange معرفی کرد تا حذف تک تک آنها که شامل صدها کوئری خواهد شد، صورت گیرد:
این روش سریع نیست؛ اما کار میکند!
البته هستند کتابخانههای ثالثی (^ و ^) که انجام به روز رسانی دستهای و یا حذف دستهای از رکوردها را تنها با یک کوئری SQL میسر میکنند؛ اما ... هنوز جزئی از EF استاندارد نشدهاند و مهمترین مشکل احتمالی این روشها، همگام نبودن context و سیستم change tacking، با نتیجهی حاصل از به روز رسانی یکبارهی صدها ردیف است.
مثال 8: حذف یک کاربر از جدول کاربران
میخواهیم کاربر شمارهی 37 را حذف کنیم.
روش انجام اینکار با SQL نویسی به صورت زیر است:
و در EF-Core برای انجام اینکار میتوان ابتدا شیء متناظر با کاربر 37 را از طریق یک کوئری به سیستم change tracking وارد کرد و سپس آنرا حذف نمود:
یک نکته: امکان سادهتر حذف یک ردیف با داشتن ID آن
کوئری گرفتن از بانک اطلاعاتی، یک روش وارد کردن شیءای به context و سیستم change tacking آن است. در این حالت عموما فرض بر این است که ID شیء را نمیدانیم. اما اگر این ID مانند مثال جاری از پیش مشخص بود، نیازی نیست تا ابتدا از بانک اطلاعاتی کوئری گرفت و کل شیء را در حافظه وارد کرد. در این حالت خاص میتوان با استفاده از روش زیر، این ID را وارد سیستم tracking کرد و سپس حالت آنرا به Deleted تغییر داد و در آخر آنرا ذخیره کرد:
در کدهای فوق میتوان سطر entry.State = EntityState.Deleted را با context.Remove(entry) نیز جایگزین کرد و هر دو به یک معنا هستند.
روش فوق چنین کوئریهایی را ایجاد میکند:
مثال 9: حذف بر اساس یک sub-query
میخواهیم تمام کاربرانی را که هیچگاه رزروی را انجام ندادهاند، حذف کنیم.
این مورد نیز با SQL نویسی مستقیم نیز توسط یک کوئری دستهای قابل انجام است:
اما همانطور که عنوان شد، EF-Core این نوع اعمال ویرایش دستهای را در طی یک تک کوئری پشتیبانی نمیکند. به همین جهت ابتدا آنها را توسط یک کوئری به context وارد کرده و سپس حذف میکنیم:
کدهای کامل این قسمت را در اینجا میتوانید مشاهده کنید.
مثال 1: افزودن ردیفی به یک جدول بانک اطلاعاتی
امکان و ویژگی جدیدی به نام SPA قرار است به مجموعه اضافه شود. اطلاعات آن که شامل موارد ذیل است، نیاز است به جدول facilities اضافه شود:
facid: 9, Name: 'Spa', membercost: 20, guestcost: 30, initialoutlay: 100000, monthlymaintenance: 800.
insert into facilities (facid, name, membercost, guestcost, initialoutlay, monthlymaintenance) values (9, 'Spa', 20, 30, 100000, 800); -- OR insert into facilities values (9, 'Spa', 20, 30, 100000, 800);
context.Facilities.Add(new Facility { Name = "Spa", MemberCost = 20, GuestCost = 30, InitialOutlay = 100000, MonthlyMaintenance = 800 }); context.SaveChanges();
مثال 2: افزودن چندین ردیف از اطلاعات به یک جدول بانک اطلاعاتی
همان مثال قبلی را درنظر بگیرید. اینبار میخواهیم دو ردیف را به آن اضافه کنیم:
facid: 9, Name: 'Spa', membercost: 20, guestcost: 30, initialoutlay: 100000, monthlymaintenance: 800. facid: 10, Name: 'Squash Court 2', membercost: 3.5, guestcost: 17.5, initialoutlay: 5000, monthlymaintenance: 80.
insert into facilities (facid, name, membercost, guestcost, initialoutlay, monthlymaintenance) values (9, 'Spa', 20, 30, 100000, 800), (10, 'Squash Court 2', 3.5, 17.5, 5000, 80);
context.Facilities.Add(new Facility { Name = "Spa", MemberCost = 20, GuestCost = 30, InitialOutlay = 100000, MonthlyMaintenance = 800 }); context.Facilities.Add(new Facility { Name = "Squash Court 2", MemberCost = 3.5M, GuestCost = 17.5M, InitialOutlay = 5000, MonthlyMaintenance = 80 }); context.SaveChanges();
مثال 3: افزودن اطلاعات محاسبه شده به یک جدول بانک اطلاعاتی
اطلاعات زیر را درنظر بگیرید:
Name: 'Spa', membercost: 20, guestcost: 30, initialoutlay: 100000, monthlymaintenance: 800.
namespace EFCorePgExercises.Entities { public class FacilityConfiguration : IEntityTypeConfiguration<Facility> { public void Configure(EntityTypeBuilder<Facility> builder) { builder.HasKey(facility => facility.FacId); builder.Property(facility => facility.FacId).IsRequired().UseIdentityColumn(seed: 0, increment: 1);
CREATE TABLE [dbo].[Facilities]( [FacId] [int] IDENTITY(0,1) NOT NULL, --- ... CONSTRAINT [PK_Facilities] PRIMARY KEY CLUSTERED ( [FacId] ASC );
مثال 4: به روز رسانی اطلاعاتی از پیش موجود
میخواهیم مقدار InitialOutlay دومین زمین تنیس را از 8000 موجود به 10000 تغییر دهیم. با توجه به اینکه ID این زمین شماره 1 است، در حالت متداول SQL نویسی، به کدهای زیر خواهیم رسید:
update facilities set initialoutlay = 10000 where facid = 1;
var facility1 = context.Facilities.Find(1); facility1.InitialOutlay = 10000; context.SaveChanges();
EF-Core برای اینکه بتواند تغییرات اعمالی به یک شیء را محاسبه کند، نیاز دارد تا آن شیء را به نحوی در سیستم change tracking خودش موجود داشته باشد. هر نوع کوئری که در EF-Core نوشته میشود و به همراه متد AsNoTracking نیست، خروجی تک تک اشیاء حاصل از آن پیش از ارائهی نهایی، وارد سیستم change tracking آن میشوند. یعنی اگر مقادیر خواص این اشیاء را تغییر داده و بر روی آنها SaveChanges را فراخوانی کنیم، کوئریهای متناظر با به روز رسانی تنها این خواص تغییر یافته به صورت خودکار محاسبه شده و به بانک اطلاعاتی اعمال میشوند.
فراخوانی متد AsNoTracking بر روی کوئریهای EF-Core، تولید پروکسیهای change tracking را غیرفعال میکند. یک چنین کوئریهایی صرفا کاربردهای گزارشگیری فقط خواندنی را دارند و نسبت به کوئریهای معمولی، سریعتر و با مصرف حافظهی کمتری هستند. بنابراین نتایج حاصل از کوئریهای متداول EF-Core، به صورت پیشفرض (یعنی بدون داشتن متد AsNoTracking) هم خواندنی و هم نوشتنی با قابلیت اعمال به بانک اطلاعاتی هستند.
مثال 5: به روز رسانی چندین ردیف و چندین جدول در یک زمان
میخواهیم مقادیر MemberCost و GuestCost دو زمین تنیس را به 6 و 30 تغییر دهیم. روش انجام اینکار با SQL نویسی معمولی به صورت زیر است:
update cd.facilities set membercost = 6, guestcost = 30 where facid in (0,1);
int[] facIds = { 0, 1 }; var tennisCourts = context.Facilities.Where(x => facIds.Contains(x.FacId)).ToList(); foreach (var tennisCourt in tennisCourts) { tennisCourt.MemberCost = 6; tennisCourt.GuestCost = 30; } context.SaveChanges();
مثال 6: به روز رسانی اطلاعات یک ردیف بر اساس اطلاعات ردیفی دیگر
میخواهیم هزینهی دومین زمین تنیس را به نحوی ویرایش کنیم که 10 درصد بیشتر از هزینهی اولین زمین تنیس باشد.
روش پیشنهادی انجام اینکار با SQL نویسی مستقیم به صورت زیر است:
update cd.facilities facs set membercost = (select membercost * 1.1 from cd.facilities where facid = 0), guestcost = (select guestcost * 1.1 from cd.facilities where facid = 0) where facs.facid = 1;
var fac0 = context.Facilities.Where(x => x.FacId == 0).First(); var fac1 = context.Facilities.Where(x => x.FacId == 1).First(); fac1.MemberCost = fac0.MemberCost * 1.1M; fac1.GuestCost = fac0.GuestCost * 1.1M; context.SaveChanges();
میخواهیم تمام اطلاعات جدول bookings را حذف کنیم.
روش انجام اینکار با SQL نویسی مستقیم به صورت زیر است:
delete from bookings
context.Bookings.RemoveRange(context.Bookings.ToList()); context.SaveChanges();
البته هستند کتابخانههای ثالثی (^ و ^) که انجام به روز رسانی دستهای و یا حذف دستهای از رکوردها را تنها با یک کوئری SQL میسر میکنند؛ اما ... هنوز جزئی از EF استاندارد نشدهاند و مهمترین مشکل احتمالی این روشها، همگام نبودن context و سیستم change tacking، با نتیجهی حاصل از به روز رسانی یکبارهی صدها ردیف است.
مثال 8: حذف یک کاربر از جدول کاربران
میخواهیم کاربر شمارهی 37 را حذف کنیم.
روش انجام اینکار با SQL نویسی به صورت زیر است:
delete from members where memid = 37;
var mem37 = context.Members.Where(x => x.MemId == 37).First(); context.Members.Remove(mem37); context.SaveChanges();
یک نکته: امکان سادهتر حذف یک ردیف با داشتن ID آن
کوئری گرفتن از بانک اطلاعاتی، یک روش وارد کردن شیءای به context و سیستم change tacking آن است. در این حالت عموما فرض بر این است که ID شیء را نمیدانیم. اما اگر این ID مانند مثال جاری از پیش مشخص بود، نیازی نیست تا ابتدا از بانک اطلاعاتی کوئری گرفت و کل شیء را در حافظه وارد کرد. در این حالت خاص میتوان با استفاده از روش زیر، این ID را وارد سیستم tracking کرد و سپس حالت آنرا به Deleted تغییر داد و در آخر آنرا ذخیره کرد:
var entry = context.Entry(new Member { MemId = 37 }); entry.State = EntityState.Deleted; context.SaveChanges();
روش فوق چنین کوئریهایی را ایجاد میکند:
SET NOCOUNT ON; DELETE FROM [Members] WHERE [MemId] = @p0; SELECT @@ROWCOUNT;
مثال 9: حذف بر اساس یک sub-query
میخواهیم تمام کاربرانی را که هیچگاه رزروی را انجام ندادهاند، حذف کنیم.
این مورد نیز با SQL نویسی مستقیم نیز توسط یک کوئری دستهای قابل انجام است:
delete from members where memid not in (select memid from cd.bookings);
var mems = context.Members.Where(x => !context.Bookings.Select(x => x.MemId).Contains(x.MemId)).ToList(); context.Members.RemoveRange(mems); context.SaveChanges();
کدهای کامل این قسمت را در اینجا میتوانید مشاهده کنید.
نظرات نظرسنجیها
آیا با وجود سیاماس فروشگاهی قدرتمندی مثل nopCommerce یا SmartStore آیا منطقی است که ما دوباره خودمان از صفر کد بزنیم؟
مطمئنا نوشتن یک سیستم جدید برای ما دلنشینتر هست ولی امروز با فاکتورهایی چون رقابت و زمان و هزینه و موراد دیگر استفاده از سیستمهای آماده بیشتر مدنظر هست به خصوص تا حد متوسط را به خوبی پشتیبانی میکنند و میتوان آنها را به صورت همگانی توسعه داده ولی اگر واقعا بخواهد اختصاصی شود نیاز به یک سیستم جدید بیشتر احساس میشود.
مطالب
NOSQL قسمت دوم
در مطلب قبلی با تعاریف سیستمهای NoSQL آشنا شدیم و به طور کلی ویژگیهای یک سیستم NoSQL را بررسی کردیم.
در این مطلب دستهبندی کلی و نوع ساختار دادهای این سیستمها و بررسی سادهترین آنها را مرور میکنیم.
در حالت کلی پایگاهای داده NoSQL به ۴ دسته تقسیم میشوند که به ترتیب پیچیدگی ذخیرهسازی دادهها عبارتند از:
به دلیل موجود بودن این نوع ساختار دادهای در اکثر کتابخانههای زبانهای برنامهنویسی ( به عنوان مثال پیادهسازیهای مختلف اینترفیس Map شامل HashTable ، HashMap و موارد دیگر در کتابخانههای JDK ) این نوع ساختار برای اکثر برنامهنویسان آشنا بوده و فراگیری آن نیز ساده میباشد.
در این مطلب دستهبندی کلی و نوع ساختار دادهای این سیستمها و بررسی سادهترین آنها را مرور میکنیم.
در حالت کلی پایگاهای داده NoSQL به ۴ دسته تقسیم میشوند که به ترتیب پیچیدگی ذخیرهسازی دادهها عبارتند از:
- Key/Value Store Databases
- Document Databases
- Graph Databases
- Column Family Databases
به دلیل موجود بودن این نوع ساختار دادهای در اکثر کتابخانههای زبانهای برنامهنویسی ( به عنوان مثال پیادهسازیهای مختلف اینترفیس Map شامل HashTable ، HashMap و موارد دیگر در کتابخانههای JDK ) این نوع ساختار برای اکثر برنامهنویسان آشنا بوده و فراگیری آن نیز ساده میباشد.
بدیهی است که اعمال فرهنگ دادهای ( درج ، حذف ،
جستجو ) در این سیستم به دلیل اینکه دادهها به صورت کلید/مقدار ذخیره
میشوند دارای پیچیدگی زمانی (1)O میباشد که بهینهترین حالت ممکن به لحاظ
طراحی میباشد. همانگونه که مستحضرید در الگوریتمهایی که دارای پیچیدگی
زمانی با مقدار ثابت دارند کم یا زیاد بودن دادهها تاثیری در کارایی
الگوریتم نداشته و همواره با هر حجم دادهای زمان ثابتی جهت پردازش نیاز
میباشد.
Key/Value Store Databases:
Key/Value Store Databases:
این سیستم سادهترین حالت از دستهبندیهای NoSQL میباشد ، به طور کلی
جهت استفاده در سیستمهایی است که دادهها متمایز از یکدیگر هستند و اصولا
Availability و یا در دسترس بودن دادهها نسبت به سایر موارد نظیر پایائی
اهمیت بالاتری دارد.
از موارد استفاده این گونه سیستمها به موارد زیر میتوان اشاره کرد:
هر یک از پیادهسازیها دارای ویژگیهای مربوط به خود هستند به عنوان مثال Memcached دادهها را صرفا در DRAM ذخیره میکند که نتیجهی آن Volatile بودن دادهها میباشد و به هیچ وجه از این سیستم جهت نگهداری دائمی دادهها نباید استفاده شود. از طرف دیگر Redis دادهها را علاوه بر حافظه اصلی در حافظه جانبی نیز ذخیره میکند که نتیجهی آن سرعت بالا در کنار پایائی میباشد.
همانگونه که در تعریف کلی عنوان شد یکی از ویژگیهای این سیستمها متنباز بودن انها میباشد که نتیجهی آن وجود پیادهسازیهای متنوع از هر کدام میباشد ، لازم است قبل از انتخاب هر سیستم به خوبی با ویژگیهای اکثر سیستمهای محبوب و پراستفاده آشنا شویم و با توجه به نیاز سیستم را انتخاب کنیم.
در مطلب بعدی با نوع دوم یعنی Document Databases آشنا خواهیم شد.
از موارد استفاده این گونه سیستمها به موارد زیر میتوان اشاره کرد:
- در پلتفرمهای اشتراک گذاری دادهها . هدف کلی صرفا هندل کردن
آپلود محتوی (باینری) و به صورت همزمان بروز کردن در سمت دیگر میباشد.(
اپلیکیشنی مانند اینستاگرام را تصور کنید) در اینگونه نرمافزارها با
تعداد بسیار زیاد کاربر و تقاضا، استفاده از این نوع پایگاه داده به مراتب
کارایی و سرعت را بالاتر میبرد. و با توجه به عدم پیشبینی حجم دادهها
یکی از ویژگیهای این نوع پایگاه داده تحت عنوان Horizontal Scaling مطرح
میشود که در صورت Overflow شدن سرور، دادهها را به سمت سرور دیگری
میتوان هدایت کرد وبدون مشکل پردازش را ادامه داد ، این ویژگی یک وجه
تمایز کارایی این سیستم با سیستمهای RDBMS میباشد که جهت مقابله با چنین
وضعیتی تنها راه پیشرو بالا بردن امکانات سرور میباشد و به طور کلی
دادهها را در یک سرور میتوان نگهداری کرد ( البته راهحلهایی نظیر
پارتیشن کردن و غیره وجود دارد که به مراتب پیچیدگی و کارایی کمتری نسبت به
Horizontal Scaling در پایگاههای داده NoSQL دارد.)
- برای Cache کردن صقحات بسیار کارا میباشد ، به عنوان مثال میتوان
آدرس درخواست را به عنوان Key در نظر گرفت و مقدار آن را نیز معادل JSON
نتیجه که توسط کلاینت پردازش خواهد شد قرار داد.
- یک نسخه کپی شده از توئیتر که کاملا توسط این نوع پایگاه داده پیاده شده است نیز از این آدرس
قابل مشاهده است. این برنامه به زبانهای php , ruby و java نوشته شده
است و سورس نیز در مخارن github میجود میباشد. (یک نمونه پیاده سازی
ایدهآل جهت آشنایی با نحوهی مدیریت دادهها در این نوع پایگاه داده)
هر یک از پیادهسازیها دارای ویژگیهای مربوط به خود هستند به عنوان مثال Memcached دادهها را صرفا در DRAM ذخیره میکند که نتیجهی آن Volatile بودن دادهها میباشد و به هیچ وجه از این سیستم جهت نگهداری دائمی دادهها نباید استفاده شود. از طرف دیگر Redis دادهها را علاوه بر حافظه اصلی در حافظه جانبی نیز ذخیره میکند که نتیجهی آن سرعت بالا در کنار پایائی میباشد.
همانگونه که در تعریف کلی عنوان شد یکی از ویژگیهای این سیستمها متنباز بودن انها میباشد که نتیجهی آن وجود پیادهسازیهای متنوع از هر کدام میباشد ، لازم است قبل از انتخاب هر سیستم به خوبی با ویژگیهای اکثر سیستمهای محبوب و پراستفاده آشنا شویم و با توجه به نیاز سیستم را انتخاب کنیم.
در مطلب بعدی با نوع دوم یعنی Document Databases آشنا خواهیم شد.
زمانیکه خاصیتی به یکی از کلاسهای نگاشتهای تعریف شده اضافه میشود یا حذف میگردد، دقیقا باید این به روز رسانی در سمت بانک اطلاعاتی هم انجام شود. امکان تهیه و همچنین اعمال اسکریپت نهایی تولید database schema مهیا است، اما ممکن است به هر علتی این کار فراموش شود. اکنون سؤال این است که آیا میتوان سریع بررسی کرد که دیتابیس مورد استفاده با نگاشتهای برنامه همخوانی و تطابق دارد؟
جهت پاسخ به این سؤال بهترین راه ایجاد یک کوئری Select بر اساس تمام خواص تعریف شده در یک کلاس است. اگر یکی از خواص یا حتی خود جدول وجود نداشته باشد، انجام این کوئری خودبخود با شکست مواجه شده و یک استثناء صادر خواهد شد. همین ایده را به سادگی میتوان با NHibernate هم پیاده سازی کرد:
public class ConfirmDatabaseMatchesMappings
{
public static void ValidateDatabaseSchemaAgainstMappings()
{
//در اینجا باید سشن فکتوری سراسری تعریف شده را دریافت و استفاده کرد
using (var session = sessionManager.OpenSession())
{
var allClassMetadata = session.SessionFactory.GetAllClassMetadata();
foreach (var entry in allClassMetadata)
{
session.CreateCriteria(entry.Value.GetMappedClass(EntityMode.Poco))
.SetMaxResults(0).List();
}
}
}
}
NHibernate.Exceptions.GenericADOException was unhandled
Message=could not execute query
...
نظرات مطالب
تبدیل html به pdf با کیفیت بالا
از این روش استفاده میکنه. به علاوه باید درنظر داشت HTMLWorker کتابخانه iTextSharp منسوخ شده در نظر گرفته میشود و دیگر توسعه نخواهد یافت و حتی نگهداری هم نمیشود. با Xml Worker آن جایگزین شده که فعلا از RTL و یونیکد پشتیبانی نمیکند.