- LocalDb نیاز دارد که پروفایل کاربر بارگذاری شده باشد
- بصورت پیش فرض وهله LocalDb متعلق به یک کاربر بوده، و خصوصی است
در قسمت قبل دیدیم چگونه باید پروفایل کاربر را بدرستی بارگذاری کنیم. در این مقاله به مالکیت وهلهها (instance ownership) میپردازیم.
مشکل وهله خصوصی
در پایان قسمت قبلی، اپلیکیشن وب را در این حالت رها کردیم:
همانطور که مشاهده میکنید با خطای زیر مواجه هستیم:
System.Data.SqlClient.SqlException: Cannot open database "OldFashionedDB" requested by the login. The login failed.
Login failed for user 'IIS APPPOOL\ASP.NET v4.0'.
این بار پیغام خطا واضح و روشن است. LocalDb با موفقیت اجرا شده و اپلیکیشن وب هم توانسته به آن وصل شود، اما این کانکشن سپس قطع شده چرا که دسترسی به وهله جاری وجود نداشته است. اکانت ApplicationPoolIdentity (در اینجا IIS APPPOOL\ASP.NET v4.0) نتوانسته به دیتابیس LocalDb وارد شود، چرا که دیتابیس مورد نظر در رشته اتصال اپلیکیشن (OldFashionedDB) وجود ندارد. عجیب است، چرا که وصل شدن به همین دیتابیس با رشته اتصال جاری در ویژوال استودیو با موفقیت انجام میشود.
همانطور که در تصویر بالا مشاهده میکنید از ابزار SQL Server Object Explorer استفاده شده است. این ابزار توسط SQL Server Data Tools معرفی شد و در نسخههای بعدی ویژوال استودیو هم وجود دارد و توسعه یافته است. چطور ممکن است ویژوال استودیو براحتی بتواند به دیتابیس وصل شود، اما اپلیکیشن وب ما با همان رشته اتصال نمیتواند دیتابیس را باز کند؟ در هر دو صورت رشته اتصال ما بدین شکل است:
Data Source=(localdb)\v11.0;Initial Catalog=OldFashionedDB;Integrated Security=True
پاسخ این است که در اینجا، دو وهله از LocalDb وجود دارد. بر خلاف وهلههای SQL Server Express که بعنوان سرویسهای ویندوزی اجرا میشوند، وهلههای LocalDb بصورت پروسسهای کاربری (user processes) اجرا میشوند. هنگامی که کاربران مختلفی سعی میکنند به LocalDb متصل شوند، برای هر کدام از آنها پروسسهای مجزایی اجرا خواهد شد. هنگامی که در ویژوال استودیو به localdb)\v11.0) وصل میشویم، وهله ای از LocalDb ساخته شده و در حساب کاربری ویندوز جاری اجرا میشود. اما هنگامی که اپلیکیشن وب ما در IIS میخواهد به همین دیتابیس وصل شود، وهله دیگری ساخته شده و در ApplicationPoolIdentity اجرا میشود. گرچه ویژوال استودیو و اپلیکیشن ما هر دو از یک رشته اتصال استفاده میکنند، اما در عمل هر کدام به وهلههای متفاوتی از LocalDb دسترسی پیدا خواهند کرد. پس مسلما دیتابیسی که توسط وهله ای در ویژوال استودیو ساخته شده است، برای اپلیکیشن وب ما در IIS در دسترس نخواهد بود.
یک مقایسه خوب از این وضعیت، پوشه My Documents در ویندوز است. فرض کنید در ویژوال استودیو کدی بنویسیم که در این پوشه یک فایل جدید میسازد. حال اگر با حساب کاربری دیگری وارد ویندوز شویم و به پوشه My Documents برویم این فایل را نخواهیم یافت. چرا که پوشه My Documents برای هر کاربر متفاوت است. بهمین شکل، وهلههای LocalDb برای هر کاربر متفاوت است و به پروسسها و دیتابیسهای مختلفی اشاره میکنند.
به همین دلیل است که اپلیکیشن وب ما میتواند بدون هیچ مشکلی روی IIS Express اجرا شود و دیتابیس را باز کند. چرا که IIS Express درست مانند LocalDb یک پروسس کاربری است. IIS Express توسط ویژوال استودیو راه اندازی میشود و روی حساب کاربری جاری اجرا میگردد، پس پروسس آن با پروسس خود ویژوال استودیو یکسان خواهد بود و هر دو زیر یک اکانت کاربری اجرا خواهند شد.
راه حل ها
درک ماهیت مشکل جاری، راه حالهای مختلفی را برای رفع آن بدست میدهد. از آنجا که هر راه حل مزایا و معایب خود را دارد، بجای معرفی یک راه حال واحد چند راهکار را بررسی میکنیم.
رویکرد 1: اجرای IIS روی کاربر جاری ویندوز
اگر مشکل، حسابهای کاربری مختلف است، چرا خود IIS را روی کاربر جاری اجرا نکنیم؟ در این صورت ویژوال استودیو و اپلیکیشن ما هر دو به یک وهله از LocalDb وصل خواهند شد و همه چیز بدرستی کار خواهد کرد. ایجاد تغییرات لازم نسبتا ساده است. IIS را اجرا کنید و Application Pool مناسب را انتخاب کنید، یعنی همان گزینه که برای اپلیکیشن شما استفاده میشود.
قسمت Advanced Settings را باز کنید:
روی دکمه سه نقطه کنار خاصیت Identity کلیک کنید تا پنجره Application Pool Identity باز شود:
در این قسمت میتوانید از حساب کاربری جاری استفاده کنید. روی دکمه Set کلیک کنید و نام کاربری و رمز عبور خود را وارد نمایید. حال اگر اپلیکیشن را مجددا اجرا کنید، همه چیز باید بدرستی اجرا شود.
خوب، معایب این رویکرد چیست؟ مسلما اجرای اپلیکیشن وب روی اکانت کاربری جاری، ریسکهای امنیتی متعددی را معرفی میکند. اگر کسی بتواند اپلیکیشن وب ما را هک کند، به تمام منابع سیستم که اکانت کاربری جاری به آنها دسترسی دارد، دسترسی خواهد داشت. اما اجرای اپلیکیشن مورد نظر روی ApplicationPoolIdentity امنیت بیشتری را ارائه میکند، چرا که اکانتهای ApplicationPoolIdentity دسترسی بسیار محدودتری به منابع سیستم محلی دارند. بنابراین استفاده از این روش بطور کلی توصیه نمیشود، اما در سناریوهای خاصی با در نظر داشتن ریسکهای امنیتی میتواند رویکرد خوبی باشد.
رویکرد 2: استفاده از وهله مشترک
یک راه حال دیگر استفاده از قابلیت instance sharing است. این قابلیت به ما این امکان را میدهد تا یک وهله LocalDb را بین کاربران یک سیستم به اشتراک بگذاریم. وهله به اشتراک گذاشته شده، توسط یک نام عمومی (public name) قابل دسترسی خواهد بود.
سادهترین راه برای به اشتراک گذاشتن وهلههای LocalDb استفاده از ابزار SqlLocalDB.exe است. بدین منظور Command Prompt را بعنوان مدیر سیستم باز کنید و فرمان زیر را اجرا نمایید:
sqllocaldb share v11.0 IIS_DB
Data Source=(localdb)\.\IIS_DB;Initial Catalog=OldFashionedDB;Integrated Security=True
پیش از آنکه اپلیکیشن وب ما بتواند به این وهله متصل شود، باید لاگینهای مورد نیاز برای ApplicationPoolIdentity را ایجاد کنیم. راه اندازی وهله ساده است، کافی است دیتابیس را در SQL Server Object Explorer باز کنید. این کار اتصالی به دیتابیس برقرار میکند و آن را زنده نگاه میدارد. برای ایجاد لاگین مورد نظر، میتوانیم در SQL Server Object Explorer یک کوئری اجرا کنیم:
create login [IIS APPPOOL\ASP.NET v4.0] from windows; exec sp_addsrvrolemember N'IIS APPPOOL\ASP.NET v4.0', sysadmin
اسکریپت بالا به اکانت ApplicationPoolIdentity سطح دسترسی کامل میدهد. در صورت امکان بهتر است از سطوح دسترسی محدودتری استفاده کنید، مثلا دسترسی به دیتابیس یا جداولی مشخص. حالا میتوانید اپلیکیشن را مجددا اجرا کنید و همه چیز بدون خطا باید کار کند.
معایب این روش چیست؟ مشکل اصلی در این رویکرد این است که پیش از آنکه اپلیکیشن ما بتواند به وهله مشترک دسترسی داشته باشد، باید وهله مورد نظر را راه اندازی و اجرا کنیم. بدین منظور، حساب کاربری ویندوزی که مالکیت وهله را دارد باید به آن وصل شود و کانکشن را زنده نگه دارد، در غیر اینصورت وهله LocalDb قابل دسترسی نخواهد بود.
رویکرد 3: استفاده از SQL Server Express
از آنجا که نسخه کامل SQL Server Express بعنوان یک سرویس ویندوزی اجرا میشود، شاید بهترین راه استفاده از همین روش باشد. کافی است یک نسخه از SQL Server Express را نصب کنیم، دیتابیس مورد نظر را در آن بسازیم و سپس به آن متصل شویم. برای این کار حتی میتوانید از ابزار جدید SQL Server Data Tools استفاده کنید، چرا که با تمام نسخههای SQL Server سازگار است. در صورت استفاده از نسخههای کامل تر، رشته اتصال ما بدین شکل تغییر خواهد کرد:
Data Source=.\SQLEXPRESS;Initial Catalog=OldFashionedDB;Integrated Security=True
create login [IIS APPPOOL\ASP.NET v4.0] from windows; exec sp_addsrvrolemember N'IIS APPPOOL\ASP.NET v4.0', sysadmin
حال اجرای مجدد اپلیکیشن باید با موفقیت انجام شود. استفاده از این روش مسلما امکان استفاده از LocalDb را از ما میگیرد. ناگفته نماند که وهلههای SQL Server Express همیشه در حال اجرا خواهند بود چرا که بصورت سرویسهای ویندوزی اجرا میشوند. همچنین استفاده از این روش ممکن است شما را با مشکلاتی هم مواجه کند. مثلا خرابی رجیستری ویندوز میتواند SQL Server Express را از کار بیاندازد و مواردی از این دست. راهکارهای دیگری هم وجود دارند که در این مقاله به آنها نپرداختیم. مثلا میتوانید از AttachDbFilename استفاده کنید یا از اسکریپتهای T-SQL برای استفاده از وهله خصوصی ASP.NET کمک بگیرید. اما این روشها دردسرهای زیادی دارند، بهمین دلیل از آنها صرفنظر کردیم.