نظرات مطالب
استفاده از خواص راهبری در Entity framework بجای Join نویسی
ممنون از مطلب مفیدتون . جالب اینه که بدون هیچ دردسری از خواص راهبری میشه برای به روز رسانی و افزودن رکورد‌های مرتبط در صورت وجود رابطه‌های صحیح و نرمال سازی دقیق پایگاه داده بهترین استفاده رو کرد ... واقعا ORM‌ها برنامه نویسارو از شر کد نویسی تکراری و خسته کننده‌ی بانک اطلاعاتی تا حد زیادی راحت کردن ...
نظرات اشتراک‌ها
کره‌جنوبی و ژاپن رکورددار بیشترین سرعت اینترنت در جهان
سرعت بیشتر؟! من از داتک اینترنت گرفتم. سه ماهه با 5 گیگ حجم اولیه. قبلا (تا یک ماه قبل) از ساعت 1 بامداد تا 7 صبح آن رایگان بود (در محاسبه حجم حساب نمی‌شد). الان یک ماه هست بدون اطلاع به کاربران، این ساعت شده از 2 بامداد تا 7 صبح. چون اطلاع نداشتم، مثل قبل از ساعت 1 بامداد هر شب دانلود می‌کردم. چند روز قبل دیدم که حجم 5 گیگ اولیه‌ام زودتر از موعد تمام شده! تبدیل این مساله به 2 بامداد، تقریبا زندگی من رو مختل کرده.
نظرات مطالب
Globalization در ASP.NET MVC - قسمت ششم
دلیل خاصی برای تفکیک این چنینی وجود نداره و همونطور که دوستمون گفتن این روشی که شما اشاره کردین مشکلات و معایبی هم به همراه داره.
روش اشاره شده تو این مطلب تو بیش از 99 درصد پروژه‌ها کفایت میکنه. فقط تو پروژه‌های بسیار بسیار بزرگ با ورودی‌های منابع بسیار بسیار زیاد (چند صد هزار و یا بیشتر) تغییر این ساختار برای رسیدن به کارایی مناسب میتونه مفید باشه.
درهرصورت اگر نیاز به تغییر ساختار جدول دارین فقط لایه دسترسی به بانک باید تغییر بکنه و فرایند کلی دسترسی به ورودی‌های منابع ذخیره شده در دیتابیس باید به همون صورتی باشه که در اینجا آورده شده. یعنی درنهایت با استفاده از سه پارامتر نام منبع، نام کالچر و عنوان کلید درخواستی کار استخراج مقدار ورودی باید انجام بشه.
مطالب
کوئری نویسی در EF Core - قسمت چهارم - اعمال تغییرات در داده‌ها
نوع دیگری از کوئری‌های پرکاربرد، کوئری‌های مرتبط با ثبت، حذف و ویرایش اطلاعات هستند که در این قسمت آن‌ها را بررسی می‌کنیم. البته این مثال‌ها از یکسری مثال کوئری‌های مرتبط با PostgreSQL، به EF-Core تبدیل و ترجمه شده‌اند. به همین جهت تطابق یک به یکی در اینجا وجود نداشته و روش شیءگرایی که ORMها برای کار با داده‌ها بکار می‌گیرند، الزاما کوئری‌های یکسانی را تولید نمی‌کنند؛ اما نتیجه‌ی نهایی آن‌ها یکی است.


مثال 1: افزودن ردیفی به یک جدول بانک اطلاعاتی

امکان و ویژگی جدیدی به نام SPA قرار است به مجموعه اضافه شود. اطلاعات آن که شامل موارد ذیل است، نیاز است به جدول facilities اضافه شود:
facid: 9, Name: 'Spa', membercost: 20, guestcost: 30, initialoutlay: 100000, monthlymaintenance: 800.
اگر قرار باشد چنین کاری را توسط دستورات SQL انجام دهیم، عموما به یکی از دو روش زیر عمل می‌شود:
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);
که معادل آن در EF-Core به صورت زیر است:
context.Facilities.Add(new Facility
                {
                    Name = "Spa",
                    MemberCost = 20,
                    GuestCost = 30,
                    InitialOutlay = 100000,
                    MonthlyMaintenance = 800
                });
context.SaveChanges();
ابتدا وهله‌ای از موجودیت Facility به DbSet مرتبط با آن اضافه می‌شود و در آخر 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.
معادل کدهای SQL چنین عملی، می‌تواند کوئری زیر باشد:
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);
و روش انجام آن در EF-Core تفاوتی با مثال قبلی ندارد:
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();
در اینجا می‌توان به هر تعدادی که نیاز است وهله‌های جدیدی از Facility را به context افزودن و سپس SaveChanges را در آخر کار فراخوانی کرد. اینکه EF-Core دستورات insert معادل را به یکباره و یا به صورت مجزایی اجرا می‌کند، به مفهومی به نام batching مرتبط است. اطلاعات بیشتر


مثال 3: افزودن اطلاعات محاسبه شده به یک جدول بانک اطلاعاتی

اطلاعات زیر را درنظر بگیرید:
Name: 'Spa', membercost: 20, guestcost: 30, initialoutlay: 100000, monthlymaintenance: 800.
در مثال اصلی عنوان شده که می‌خواهیم ID آن‌را یکی بیشتر از ردیف قبلی ثبت کنیم. در EF-Core و تنظیمات موجودیت‌هایی که داریم:
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);
چون ستون ID به صورت خود افزایش یابنده معرفی شده‌است که از صفر شروع می‌شود و به صورت خودکار توسط بانک اطلاعاتی یکی یکی افزایش می‌یابد، نیازی به حل این مساله وجود ندارد. چون ID افزایش یابنده را خود بانک اطلاعاتی محاسبه می‌کند. همچنین به همین علت در مثال‌های قبلی نیز ID را به صورت مستقیمی مقدار دهی نکردیم. اگر نیاز به انجام چنین کاری وجود داشته باشد (ذکر صریح ID خاصی)، با توجه به طراحی بانک اطلاعاتی حاصل از این تنظیمات:
CREATE TABLE [dbo].[Facilities](
[FacId] [int] IDENTITY(0,1) NOT NULL,
--- ...
 CONSTRAINT [PK_Facilities] PRIMARY KEY CLUSTERED 
(
[FacId] ASC
);
باید مانند مثال ثبت اطلاعات اولیه‌ی در بانک اطلاعاتی در قسمت اول این سری، از روش SET IDENTITY_INSERT Facilities ON استفاده کرد تا بتوان مجوز ثبت دستی این ID کنترل شده‌ی توسط بانک اطلاعاتی را پیدا کرد.


مثال 4: به روز رسانی اطلاعاتی از پیش موجود

می‌خواهیم مقدار InitialOutlay دومین زمین تنیس را از 8000 موجود به 10000 تغییر دهیم. با توجه به اینکه ID این زمین شماره 1 است، در حالت متداول SQL نویسی، به کدهای زیر خواهیم رسید:
update facilities
    set initialoutlay = 10000
    where facid = 1;
که معادل EF-Core آن به صورت زیر است:
var facility1 = context.Facilities.Find(1);
facility1.InitialOutlay = 10000;
context.SaveChanges();
این دستورات کوئری مشابهی را تولید نمی‌کنند. ابتدا موجودیت متناظر با 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 نویسی معمولی به صورت زیر است:
update cd.facilities
    set
        membercost = 6,
        guestcost = 30
    where facid in (0,1);
اما همانطور که عنوان شد در EF-Core ابتدا باید اشیاء متناظر با این زمین‌های تنیس را در سیستم change tacking موجود داشت و سپس نسبت به ویرایش آن‌ها اقدام نمود. یکی از روش‌های وارد کردن اشیاء به سیستم change tacking، نوشتن کوئری‌های بدون متد AsNoTracking است و سپس به روز رسانی نتایج حاصل از آن‌ها که اکنون توسط پروکسی‌های change tracking محصور شده‌اند و در آخر فراخوانی SaveChanges بر روی context جاری:
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;
در EF-Core می‌توان اشیاء متناظر با این دو زمین تنیس را ابتدا واکشی کرد، سپس تغییر داد و در نهایت ذخیره کرد:
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();


مثال 7: حذف تمام اطلاعات یک جدول

می‌خواهیم تمام اطلاعات جدول bookings را حذف کنیم.
روش انجام اینکار با SQL نویسی مستقیم به صورت زیر است:
delete from bookings
اما ... این تک کوئری، معادلی را در EF-Core استاندارد ندارد. چون EF-Core نیاز دارد مدام تمام اطلاعات ویرایشی/حذف و به روز رسانی را در context و سیستم change tracking خودش داشته باشد، ابتدا باید توسط یک کوئری لیست اشیاء مدنظر را تهیه کرد و سپس آن‌را به متد RemoveRange معرفی کرد تا حذف تک تک آن‌ها که شامل صدها کوئری خواهد شد، صورت گیرد:
context.Bookings.RemoveRange(context.Bookings.ToList());
context.SaveChanges();
این روش سریع نیست؛ اما کار می‌کند!
البته هستند کتابخانه‌های ثالثی (^ و ^) که انجام به روز رسانی دسته‌ای و یا حذف دسته‌ای از رکوردها را تنها با یک کوئری SQL میسر می‌کنند؛ اما ... هنوز جزئی از EF استاندارد نشده‌اند و مهم‌ترین مشکل احتمالی این روش‌ها، همگام نبودن context و سیستم change tacking، با نتیجه‌ی حاصل از به روز رسانی یکباره‌ی صدها ردیف است.



مثال 8: حذف یک کاربر از جدول کاربران

می‌خواهیم کاربر شماره‌ی 37 را حذف کنیم.
روش انجام اینکار با SQL نویسی به صورت زیر است:
delete from members where memid = 37;
و در EF-Core برای انجام اینکار می‌توان ابتدا شیء متناظر با کاربر 37 را از طریق یک کوئری به سیستم change tracking وارد کرد و سپس آن‌را حذف نمود:
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();
در کدهای فوق می‌توان سطر entry.State = EntityState.Deleted را با context.Remove(entry) نیز جایگزین کرد و هر دو به یک معنا هستند.
روش فوق چنین کوئری‌هایی را ایجاد می‌کند:
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);
اما همانطور که عنوان شد، EF-Core این نوع اعمال ویرایش دسته‌ای را در طی یک تک کوئری پشتیبانی نمی‌کند. به همین جهت ابتدا آن‌ها را توسط یک کوئری به context وارد کرده و سپس حذف می‌کنیم:
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 به ۴ دسته تقسیم می‌شوند که به ترتیب پیچیدگی ذخیره‌سازی داده‌ها عبارتند از:
  • Key/Value Store Databases
  • Document Databases
  • Graph Databases
  • Column Family Databases
  در حالت کلی در  پایگاه‌‌های‌داده NoSQL داده‌ها در قالب KEY/VALUE (کلید/مقدار) نگه‌داری می‌شوند ، به این صورت که مقادیر توسط کلید یکتایی نگاشت شده و ذخیره می‌شوند، هر مقدار صرفا توسط همان کلید نگاشت شده قابل بازگردانی می‌باشد و راهی جهت دریافت مقدار بدون دانستن کلید وجود ندارد . در این ساختار‌داده منظور از مقادیر، داده‌های اصلی برنامه‌  هستند که نیاز به نگه‌داری دارند و کلید‌ها نیز رشته‌هایی هستند که توسط برنامه‌نویس ایجاد می‌شوند.
  به دلیل موجود بودن این نوع ساختار داده‌ای در اکثر کتابخانه‌های زبان‌های برنامه‌نویسی ( به عنوان مثال پیاده‌سازی‌های مختلف اینترفیس Map شامل HashTable ، HashMap و موارد دیگر در کتابخانه‌های JDK ) این نوع ساختار برای اکثر برنامه‌نویسان آشنا بوده و فراگیری آن نیز ساده می‌باشد.
  بدیهی است که اعمال فرهنگ داده‌ای ( درج ، حذف ، جستجو ) در این سیستم به دلیل اینکه داده‌ها به صورت کلید/مقدار ذخیره می‌شوند دارای پیچیدگی زمانی (1)O می‌باشد که بهینه‌ترین حالت ممکن به لحاظ طراحی می‌باشد. همان‌گونه که مستحضرید در الگوریتم‌هایی که دارای پیچیدگی زمانی با مقدار ثابت دارند کم یا زیاد بودن داده‌ها تاثیری در کارایی الگوریتم نداشته و همواره با هر حجم داده‌ای زمان ثابتی جهت پردازش نیاز می‌باشد.
 

Key/Value Store Databases:
این سیستم  ساده‌ترین حالت از دسته‌بندی‌های NoSQL می‌باشد ، به طور کلی جهت استفاده در سیستم‌هایی است که داده‌ها متمایز از یکدیگر هستند و اصولا Availability و یا در دسترس بودن داده‌ها نسبت به سایر موارد نظیر پایائی اهمیت بالاتری دارد.

از موارد استفاده این گونه سیستم‌ها به موارد زیر می‌توان اشاره کرد:
  • در پلتفرم‌های اشتراک گذاری داده‌ها . هدف کلی صرفا هندل کردن آپلود محتوی (باینری) و به صورت همزمان بروز کردن در سمت دیگر می‌باشد.( اپلیکیشنی مانند اینستاگرام را تصور کنید) در اینگونه نرم‌افزار‌ها با تعداد بسیار زیاد کاربر و تقاضا، استفاده از این نوع پایگاه داده به مراتب کارایی و سرعت را بالاتر می‌برد. و با توجه به عدم پیش‌بینی حجم داده‌ها یکی از ویژگی‌های این نوع پایگاه داده تحت عنوان Horizontal Scaling مطرح می‌شود که در صورت Overflow شدن سرور، داده‌ها را به سمت سرور دیگری می‌توان هدایت کرد وبدون مشکل پردازش را  ادامه داد ، این ویژگی یک وجه تمایز کارایی این سیستم با سیستم‌های RDBMS می‌باشد که جهت مقابله با چنین وضعیتی تنها راه پیش‌رو بالا بردن امکانات سرور می‌باشد و به طور کلی داده‌ها را در یک سرور می‌توان نگه‌داری کرد ( البته راه‌حل‌هایی نظیر پارتیشن کردن و غیره وجود دارد که به مراتب پیچیدگی و کارایی کمتری نسبت به Horizontal Scaling در پایگاه‌های داده NoSQL دارد.)
  • برای Cache کردن صقحات بسیار کارا می‌باشد ، به عنوان مثال می‌توان آدرس درخواست را به عنوان Key در نظر گرفت و مقدار آن را نیز معادل JSON نتیجه که توسط کلاینت پردازش خواهد شد قرار داد.
  • ‌یک نسخه کپی شده از توئیتر که کاملا توسط این نوع پایگاه داده پیاده شده است نیز از این آدرس قابل مشاهده است. این برنامه به زبان‌های php , ruby و java  نوشته شده است و سورس نیز در مخارن github می‌جود می‌باشد. (یک نمونه پیاده سازی اید‌ه‌آل جهت آشنایی با  نحوه‌ی مدیریت داده‌ها در این نوع پایگاه داده)
از پیاده‌سازی‌های این نوع پایگاه داده به موارد زیر می‌توان اشاره کرد:
  هر یک از پیاده‌سازی‌ها دارای ویژگی‌های مربوط به خود هستند به عنوان مثال Memcached داده‌ها را صرفا در DRAM ذخیره می‌کند که نتیجه‌ی آن Volatile بودن داده‌ها می‌باشد و به هیچ وجه از این سیستم جهت نگهداری دائمی داده‌ها نباید استفاده شود. از طرف دیگر Redis داده‌ها را علاوه بر حافظه اصلی در حافظه جانبی نیز ذخیره می‌کند که نتیجه‌ی آن سرعت بالا در کنار پایائی می‌باشد.
همان‌گونه که در تعریف کلی عنوان شد یکی از ویژگی‌های این سیستم‌ها متن‌باز بودن انها می‌باشد که نتیجه‌ی آن وجود پیاده‌سازی‌های متنوع از هر کدام می‌باشد ، لازم است قبل از انتخاب هر سیستم به خوبی با ویژگی‌های اکثر سیستم‌های محبوب و پراستفاده آشنا شویم و با توجه به نیاز سیستم را انتخاب کنیم.
در مطلب بعدی با نوع دوم یعنی Document Databases آشنا خواهیم شد.
 
مطالب
آیا دیتابیس مورد استفاده در NHibernate با نگاشت‌های تعریف شده همخوانی دارد؟

زمانیکه خاصیتی به یکی از کلاس‌های نگاشت‌های تعریف شده اضافه می‌شود یا حذف می‌گردد، دقیقا باید این به روز رسانی در سمت بانک اطلاعاتی هم انجام شود. امکان تهیه و همچنین اعمال اسکریپت نهایی تولید 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 و یونیکد پشتیبانی نمی‌کند.