نمایش ساختارهای درختی توسط jqGrid
+ امکان اتصال دو جدول با کلید خارجی نیز در اینجا وجود دارد:
public ActionResult GetComments(JqGridRequest request, int? nodeid, int? parentid, int? n_level)
if (nodeid == null) { productsQuery = productsQuery.Where(x => x.ParentId == null); }
else { // آی دی یک گره میتواند کلید خارجی یک جدول دیگر باشد productsQuery = productsQuery.Where(x => x.ParentId == nodeid.Value); }
بازگردانی پایگاه داده بدون فایل لاگ
DECLARE @DBName VARCHAR(64) = 'databasename' DECLARE @ErrorLog AS TABLE([LogDate] CHAR(24), [ProcessInfo] VARCHAR(64), [TEXT] VARCHAR(MAX)) INSERT INTO @ErrorLog EXEC sys.xp_readerrorlog 0, 1, 'Recovery of database', @DBName SELECT TOP 5 [LogDate] ,SUBSTRING([TEXT], CHARINDEX(') is ', [TEXT]) + 4,CHARINDEX(' complete (', [TEXT]) - CHARINDEX(') is ', [TEXT]) - 4) AS PercentComplete ,CAST(SUBSTRING([TEXT], CHARINDEX('approximately', [TEXT]) + 13,CHARINDEX(' seconds remain', [TEXT]) - CHARINDEX('approximately', [TEXT]) - 13) AS FLOAT)/60.0 AS MinutesRemaining ,CAST(SUBSTRING([TEXT], CHARINDEX('approximately', [TEXT]) + 13,CHARINDEX(' seconds remain', [TEXT]) - CHARINDEX('approximately', [TEXT]) - 13) AS FLOAT)/60.0/60.0 AS HoursRemaining ,[TEXT] FROM @ErrorLog ORDER BY [LogDate] DESC
در ضمن دیتابیس روی درایو D هست و فضای چند ده گیگ خالی داره. حجم فایل ldf هم تا حدود 400 مگ هست. وقتی هم یک کوئری بخوام روی دیتابیس اجرا کنم خطای زیر رو میده:
معرفی قالبهای جدید شروع پروژههای Blazor در دات نت 8 به همراه قسمت Identity
در قسمت دوم این سری، با قالبهای جدید شروع پروژههای Blazor 8x آشنا شدیم و هدف ما در آنجا بیشتر بررسی حالتهای مختلف رندر Blazor در دات نت 8 بود. تمام این قالبها به همراه یک سوئیچ دیگر هم به نام auth-- هستند که توسط آن و با مقدار دهی Individual که به معنای Individual accounts است، میتوان کدهای پیشفرض و ابتدایی Identity UI جدید را نیز به قالب در حال ایجاد، به صورت خودکار اضافه کرد؛ یعنی به صورت زیر:
اجرای قسمتهای تعاملی برنامه بر روی سرور؛ به همراه کدهای Identity:
dotnet new blazor --interactivity Server --auth Individual
اجرای قسمتهای تعاملی برنامه در مرورگر، توسط فناوری وباسمبلی؛ به همراه کدهای Identity:
dotnet new blazor --interactivity WebAssembly --auth Individual
برای اجرای قسمتهای تعاملی برنامه، ابتدا حالت Server فعالسازی میشود تا فایلهای WebAssembly دریافت شوند، سپس فقط از WebAssembly استفاده میکند؛ به همراه کدهای Identity:
dotnet new blazor --interactivity Auto --auth Individual
فقط از حالت SSR یا همان static server rendering استفاده میشود (این نوع برنامهها تعاملی نیستند)؛ به همراه کدهای Identity:
dotnet new blazor --interactivity None --auth Individual
و یا توسط پرچم all-interactive--، که interactive render mode را در ریشهی برنامه قرار میدهد؛ به همراه کدهای Identity:
dotnet new blazor --all-interactive --auth Individual
یک نکته: بانک اطلاعاتی پیشفرض مورد استفادهی در این نوع پروژهها، SQLite است. برای تغییر آن میتوانید از پرچم use-local-db-- هم استفاده کنید تا از LocalDB بجای SQLite استفاده کند.
Identity UI جدید Blazor در دات نت 8، یک بازنویسی کامل است
در نگارشهای قبلی Blazor هم امکان افزودن Identity UI، به پروژههای Blazor وجود داشت (اطلاعات بیشتر)، اما ... آن پیاده سازی، کاملا مبتنی بر Razor pages بود. یعنی کاربر، برای کار با آن مجبور بود از فضای برای مثال Blazor Server خارج شده و وارد فضای جدید ASP.NET Core شود تا بتواند، Identity UI نوشته شدهی با صفحات cshtml. را اجرا کند و به اجزای آن دسترسی پیدا کند (یعنی عملا آن قسمت UI اعتبارسنجی، Blazor ای نبود) و پس از اینکار، مجددا به سمت برنامهی Blazor هدایت شود؛ اما ... این مشکل در دات نت 8 با ارائهی صفحات SSR برطرف شدهاست.
همانطور که در قسمت قبل نیز بررسی کردیم، صفحات SSR، طول عمر کوتاهی دارند و هدف آنها تنها ارسال یک HTML استاتیک به مرورگر کاربر است؛ اما ... دسترسی کاملی را به HttpContext برنامهی سمت سرور دارند و این دقیقا چیزی است که زیر ساخت Identity، برای کار و تامین کوکیهای مورد نیاز خودش، احتیاج دارد. صفحات Identity UI از یک طرف از HttpContext برای نوشتن کوکی لاگین موفقیت آمیز در مرورگر کاربر استفاده میکنند (در این سیستم، هرجائی متدهای XyzSignInAsync وجود دارد، در پشت صحنه و در پایان کار، سبب درج یک کوکی اعتبارسنجی و احراز هویت در مرورگر کاربر نیز خواهد شد) و از طرف دیگر با استفاده از میانافزارهای اعتبارسنجی و احراز هویت ASP.NET Core، این کوکیها را به صورت خودکار پردازش کرده و از آنها جهت ساخت خودکار شیء User قابل دسترسی در این صفحات (شیء context.User.Identity@)، استفاده میکنند.
به همین جهت تمام صفحات Identity UI ارائه شده در Blazor 8x، از نوع SSR هستند و اگر در آنها از فرمی استفاده شده، دقیقا همان فرمهای تعاملی است که در قسمت چهارم این سری بررسی کردیم. یعنی صرفا بخاطر داشتن یک فرم، ضرورتی به استفادهی از جزایر تعاملی Blazor Server و یا Blazor WASM را ندیدهاند و اینگونه فرمها را بر اساس مدل جدید فرمهای تعاملی Blazor 8x پیاده سازی کردهاند. بنابراین این صفحات کاملا یکدست هستند و از ابتدا تا انتها، به صورت یکپارچه بر اساس مدل SSR کار میکنند (که در اصل خیلی شبیه به Razor pages یا Viewهای MVC هستند) و جزیره، جزیرهای، طراحی نشدهاند.
روش دسترسی به HttpContext در صفحات SSR
اگر به کدهای Identity UI قالب آغازین یک پروژه که در ابتدای بحث روش تولید آنها بیان شد، مراجعه کنید، استفاده از یک چنین «پارامترهای آبشاری» را میتوان مشاهده کرد:
@code { [CascadingParameter] public HttpContext HttpContext { get; set; } = default!;
services.TryAddCascadingValue(sp => sp.GetRequiredService<EndpointHtmlRenderer>().HttpContext);
در کدهای Identity UI ارائه شده، از این CascadingParameter برای مثال جهت خروج از برنامه (HttpContext.SignOutAsync) و یا دسترسی به اطلاعات هدرهای رسید (if (HttpMethods.IsGet(HttpContext.Request.Method)))، دسترسی به سرویسها (()<HttpContext.Features.Get<ITrackingConsentFeature)، تامین مقدار Cancellation Token به کمک HttpContext.RequestAborted و یا حتی در صفحهی جدید Error.razor که آن نیز یک صفحهی SSR است، برای دریافت HttpContext?.TraceIdentifier استفادهی مستقیم شدهاست.
نکتهی مهم: باید بهخاطر داشت که فقط و فقط در صفحات SSR است که میتوان به HttpContext به نحو آبشاری فوق دسترسی یافت و همانطور که در قسمت قبل نیز بررسی شد، سایر حالات رندر Blazor از دسترسی به آن، پشتیبانی نمیکنند و اگر چنین پارامتری را تنظیم کردید، نال دریافت میکنید.
بررسی تفاوتهای تنظیمات ابتدایی قالب جدید Identity UI در Blazor 8x با نگارشهای قبلی آن
مطالب و نکات مرتبط با قالب قبلی را در مطلب «Blazor 5x - قسمت 22 - احراز هویت و اعتبارسنجی کاربران Blazor Server - بخش 2 - ورود به سیستم و خروج از آن» میتوانید مشاهده کنید.
در قسمت سوم این سری، روش ارتقاء یک برنامهی قدیمی Blazor Server را به نگارش 8x آن بررسی کردیم و یکی از تغییرات مهم آن، حذف فایلهای cshtml. ای آغاز برنامه و انتقال وظایف آن، به فایل جدید App.razor و انتقال مسیریاب Blazor به فایل جدید Routes.razor است که پیشتر در فایل App.razor نگارشهای قبلی Blazor وجود داشت.
در این نگارش جدید، محتوای فایل Routes.razor به همراه قالب Identity UI به صورت زیر است:
<Router AppAssembly="@typeof(Program).Assembly"> <Found Context="routeData"> <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(Layout.MainLayout)" /> <FocusOnNavigate RouteData="@routeData" Selector="h1" /> </Found> </Router>
اما ... در اینجا با یک نگارش ساده شده سروکار داریم؛ از این جهت که برنامههای جدید، به همراه جزایر تعاملی هم میتوانند باشند و باید بتوان این AuthenticationState را به آنها هم ارسال کرد. به همین جهت مفهوم جدید مقادیر آبشاری سطح ریشه (Root-level cascading values) که پیشتر در این بحث معرفی شد، در اینجا برای معرفی AuthenticationState استفاده شدهاست.
در اینجا کامپوننت جدید FocusOnNavigate را هم مشاهده میکنید. با استفاده از این کامپوننت و براساس CSS Selector معرفی شده، پس از هدایت به یک صفحهی جدید، این المان مشخص شده دارای focus خواهد شد. هدف از آن، اطلاع رسانی به screen readerها در مورد هدایت به صفحهای دیگر است (برای مثال، کمک به نابیناها برای درک بهتر وضعیت جاری).
همچنین در اینجا المان NotFound را هم مشاهده نمیکنید. این المان فقط در برنامههای WASM جهت سازگاری با نگارشهای قبلی، هنوز هم قابل استفادهاست. جایگزین آنرا در قسمت سوم این سری، برای برنامههای Blazor server در بخش «ایجاد فایل جدید Routes.razor و مدیریت سراسری خطاها و صفحات یافت نشده» آن بررسی کردیم.
روش انتقال اطلاعات سراسری اعتبارسنجی یک کاربر به کامپوننتها و جزایر تعاملی واقع در صفحات SSR
مشکل! زمانیکه از ترکیب صفحات SSR و جزایر تعاملی واقع در آن استفاده میکنیم ... جزایر واقع در آنها دیگر این مقادیر آبشاری را دریافت نمیکنند و این مقادیر در آنها نال است. برای حل این مشکل در Blazor 8x، باید مقادیر آبشاری سطح ریشه را (Root-level cascading values) به صورت زیر در فایل Program.cs برنامه ثبت کرد:
builder.Services.AddCascadingValue(sp =>new Preferences { Theme ="Dark" });
builder.Services.AddCascadingAuthenticationState(); builder.Services.AddScoped<AuthenticationStateProvider, IdentityRevalidatingAuthenticationStateProvider>();
این AuthenticationStateProvider سفارشی جدید هم در فایل اختصاصی IdentityRevalidatingAuthenticationStateProvider.cs پوشهی Identity قالب پروژههای جدید Blazor 8x که به همراه اعتبارسنجی هستند، قابل مشاهدهاست.
یا اگر به قالبهای پروژههای WASM دار مراجعه کنید، تعریف به این صورت تغییر کردهاست؛ اما مفهوم آن یکی است:
builder.Services.AddCascadingAuthenticationState(); builder.Services.AddScoped<AuthenticationStateProvider, PersistingServerAuthenticationStateProvider>();
AuthenticationStateProviderهای سفارشی مانند کلاسهای IdentityRevalidatingAuthenticationStateProvider و PersistingServerAuthenticationStateProvider که در این قالبها موجود هستند، چون به صورت آبشاری کار تامین AuthenticationState را انجام میدهند، به این ترتیب میتوان به شیء context.User.Identity@ در جزایر تعاملی نیز به سادگی دسترسی داشت.
@page "/auth" @using Microsoft.AspNetCore.Authorization @attribute [Authorize] <PageTitle>Auth</PageTitle> <h1>You are authenticated</h1> <AuthorizeView> Hello @context.User.Identity?.Name! </AuthorizeView>
سؤال: چگونه یک پروژهی سمت سرور، اطلاعات اعتبارسنجی خودش را با یک پروژهی WASM سمت کلاینت به اشتراک میگذارد (برای مثال در حالت رندر Auto)؟ این انتقال اطلاعات باتوجه به یکسان نبودن محل اجرای این دو پروژه (یکی بر روی کامپیوتر سرور و دیگری بر روی مرورگر کلاینت، در کامپیوتری دیگر) چگونه انجام میشود؟ این مورد را در قسمت بعد، با معرفی PersistentComponentState و «فیلدهای مخفی» مرتبط با آن، بررسی میکنیم.
public AddUserStatus Add(User user) { if (ExistsByEmail(user.Email)) return AddUserStatus.EmailExist; if (ExistsByUserName(user.UserName)) return AddUserStatus.UserNameExist; _users.Add(user); return AddUserStatus.AddingUserSuccessfully; }
using System.Linq; using System.Web.Mvc; using Iris.Datalayer.Context; namespace Iris.Web.Controllers { public class MigrationController : Controller { public ActionResult RemoveDuplicateUsers() { var db = new IrisDbContext(); var lstDuplicateUserGroup = db.Users .GroupBy(u => u.UserName) .Where(g => g.Count() > 1) .ToList(); foreach (var duplicateUserGroup in lstDuplicateUserGroup) { foreach (var user in duplicateUserGroup.Skip(1).Where(user => user.UserMetaData != null)) { db.UserMetaDatas.Remove(user.UserMetaData); } db.Users.RemoveRange(duplicateUserGroup.Skip(1)); } db.SaveChanges(); return new EmptyResult(); } } }
مقایسه ساختار جداول دیتابیس کاربران IRIS با ASP.NET Identity
ساختار جداول ASP.NET Identity به شکل زیر است:
ساختار جداول سیستم کنونی هم بدین شکل است:
همان طور که مشخص است در هر دو سیستم، بین ساختار جداول و رابطهی بین آنها شباهتها و تفاوت هایی وجود دارد. سیستم Identity دو جدول بیشتر از IRIS دارد و برای جداولی که در سیستم کنونی وجود ندارند نیاز به انجام کاری نیست و به هنگام پیاده سازی Identity، این جداول به صورت خودکار به دیتابیس اضافه خواهند شد.
دو جدول مشترک در این دو سیستم، جداول Users و Roles هستندکه نحوهی ارتباطشان با یکدیگر متفاوت است. در Iris بین User و Role رابطهی یک به چند وجود دارد ولی در Identity، رابطهی بین این دو جدول چند به چند است و جدول واسط بین آنها نیز UserRoles نام دارد.
از آن جایی که من قصد دارم در سیستم جدید هم رابطهی بین کاربر و نقش چند به چند باشد، به پیش فرضهای Identity کاری ندارم. به رابطهی کنونی یک به چند کاربر و نقشش نیز دست نمیگذارم تا در انتها با یک کوئری از دیتابیس، اطلاعات نقشهای کاربران را به جدول جدیدش منتقل کنم.
جدولی که در هر دو سیستم مشترک است و هستهی آنها را تشکیل میدهد، جدول Users است. اگر دقت کنید میبینید که این جدول در هر دو سیستم، دارای یک سری فیلد مشترک است که دقیقا هم نام هستند مثل Id، UserName و Email؛ پس این فیلدها از نظر کاربرد در هر دو سیستم یکسان هستند و مشکلی ایجاد نمیکنند.
یک سری فیلد هم در جدول User در سیستم IRIS هست که در Identity نیست و بلعکس. با این فیلدها نیز کاری نداریم چون در هر دو سیستم کار مخصوص به خود را انجام میدهند و تداخلی در کار یکدیگر ایجاد نمیکنند.
اما فیلدی که برای ذخیره سازی پسورد در هر دو سیستم استفاده میشود دارای نامهای متفاوتی است. در Iris این فیلد Password نام دارد و در Identity نامش PasswordHash است.
برای اینکه در سیستم کنونی، نام فیلد Password جدول User را به PasswordHash تغییر دهیم قدمهای زیر را بر میداریم:
وارد پروژهی DomainClasses شده و کلاس User را باز کنید. سپس نام خاصیت Password را به PasswordHash تغییر دهید. پس از این تغییر بلافاصله یک گزینه زیر آن نمایان میشود که میخواهد در تمام جاهایی که از این نام استفاده شده است را به نام جدید تغییر دهد؛ آن را انتخاب کرده تا همه جا Password به PasswordHash تغییر کند.
برای این که این تغییر نام بر روی دیتابیس نیز اعمال شود باید از Migration استفاده کرد. در اینجا من از مهاجرت دستی که بر اساس کد هست استفاده میکنم تا هم بتوانم کدهای مهاجرت را پیش از اعمال بررسی و هم تاریخچهای از تغییرات را ثبت کنم.
برای این کار، Package Manager Console را باز کرده و از نوار بالایی آن، پروژه پیش فرض را بر روی DataLayer قرار دهید. سپس در کنسول، دستور زیر را وارد کنید:
Add-Migration Rename_PasswordToPasswordHash_User
اگر وارد پوشه Migrations پروژه DataLayer خود شوید، باید کلاسی با نامی شبیه به 201510090808056_Rename_PasswordToPasswordHash_User ببینید. اگر آن را باز کنید کدهای زیر را خواهید دید:
public partial class Rename_PasswordToPasswordHash_User : DbMigration { public override void Up() { AddColumn("dbo.Users", "PasswordHash", c => c.String(nullable: false, maxLength: 200)); DropColumn("dbo.Users", "Password"); } public override void Down() { AddColumn("dbo.Users", "Password", c => c.String(nullable: false, maxLength: 200)); DropColumn("dbo.Users", "PasswordHash"); } }
بدیهی هست که این کدها عمل حذف ستون Password را انجام میدهند که سبب از دست رفتن اطلاعات میشود. کدهای فوق را به شکل زیر ویرایش کنید تا تنها سبب تغییر نام ستون Password به PasswordHash شود.
public partial class Rename_PasswordToPasswordHash_User : DbMigration { public override void Up() { RenameColumn("dbo.Users", "Password", "PasswordHash"); } public override void Down() { RenameColumn("dbo.Users", "PasswordHash", "Password"); } }
سپس باز در کنسول دستور Update-Database را وارد کنید تا تغییرات بر روی دیتابیس اعمال شود.
دلیل اینکه این قسمت را مفصل بیان کردم این بود که میخواستم در مهاجرت از سیستم اعتبارسنجی خودتان به ASP.NET Identity دید بهتری داشته باشید.
تا به این جای کار فقط پایگاه داده سیستم کنونی را برای مهاجرت آماده کردیم و هنوز ASP.NET Identity را وارد پروژه نکردیم. در بخشهای بعدی Identity را نصب کرده و تغییرات لازم را هم انجام میدهیم.
LocalDB چیست؟
- هاست اشتراکی باید این بانک اطلاعاتی را پیشتر نصب کرده باشد.
مانند SQL Server CE نیست که با توزیع چند DLL مشکل آن برطرف شود و نیازی به نصب نداشته باشد.
سلام
زمانی که کاربر یک درخواست از نوع POST را به API ارسال میکنه، نتیجه انجام عملیات در متغیری با نام IsSuccess برگردانده میشه. اگر مقدار این متغیر برابر false باشه یعنی متغیر ErrorList حاوی پیغام است.
سناریو:
- نام Entity در این مثال Product هست که پنج Navigation Property داره که با Entityهای دیگر دارای Relation هستند.
- لایه Application قبل از اینکه در Entity یک ردیف جدید ثبت کنه ابتدا با دستور Any مقدار یکی از Propertyها را بررسی میکنه و اگر وجود نداشت، یک Error در ErrorList اضافه میکنه و نتیجه را بصورت IsSeccess=false بر میگردونه.
- در واقع حالا کاربر مطلع هست که مثلا ProductTypeId اشتباه است و اصلا ProductTypeی با این شناسه وجود نداره.
سوال:
- آیا ضروریه تا به ازای هر کلید خارجی که در Entity تعریف شده بدین صورت اعتبار تمام آنها بررسی و به کلاینت اعلام شود؟
- اگر تعداد کلیدهای خارجی در یک Entity زیاد باشد راه حل چیست؟
- آیا اگر اطلاعات را مستقیما به بانک اطلاعاتی ارسال کنیم تا خود بانک اطلاعاتی صحت وجود این کلیدها را بررسی کند بهتر است یا خیر؟
- اگر برعهده بانک اطلاعاتی بگذاریم چطور باید به کلاینت و به ازای هر کلید خارجی که باعث بروز Exception شده اطلاع رسانی کنیم؟
- در مجموع روش مناسب کدام است؟
تشکر
1- نیاز به تواناییهای موجود در برنامههای Desktop را دارید اما همچنین نیاز است تا آنها را تحت وب نیز ارائه دهید.
یکی از دلایل اقبال به برنامههای تحت وب در سازمانها عدم نیاز به نصب آنها و توزیع هر چه سادهتر اینگونه برنامهها در شبکه است. تنها کافی است چند فایل را بر روی سرور به روز رسانی کنید و پس از آن تمام کلاینتها از آخرین نگارش برنامه شما بهرهمند خواهند شد (+). توزیع برنامههای سیلورلایت نیز به همین منوال است. علاوه بر آن استفاده از فناورهایی مانند MEF امکان ماژولار ساختن برنامه و دریافت آخرین ماژولهای تهیه شده (فایلهای XAP مجزای از برنامه به صورت افزونه) را بر اساس انتخاب و سطح دسترسی کاربر نیز میسر میسازد.
2- نیاز است تا یک برنامهی گرافیکی تمام عیار را تحت وب ارائه دهید.
تواناییهای XAML به همراه یکی از زبانهای دات نت جهت خلق جلوههای بصری، پویانمایی و گرافیکی بسیار بسیار فراتر از کتابخانههای جاوا اسکریپتی موجود هستند و نکتهی مهم آنها هم این است که لازم نیست حتما یک متخصص مثلا جاوا اسکریپت باشید تا بتوانید برای مثال پویانمایی را ارائه دهید. امکان استفاده از انواع و اقسام قلمها و قرار دادن آنها در برنامه، امکان استفاده از گرافیک برداری و غیره را نیز لحاظ کنید.
3- برنامهی شما نیاز است تا از طریق وب توزیع شود اما نیاز به سطح دسترسی بیشتری نسبت به یک برنامهی وب معمولی دارد.
تمام برنامههای توزیع شده از طریق مرورگرها محدود به سطوح دسترسی آنها نیز هستند. اما امکان نصب خارج از مرورگر برنامههای سیلورلایت نیز وجود دارد. در این حالت میتوان در صورت نیاز و همچنین تائید صریح کاربر، به سطوح دسترسی بیشتری دست یافت. برای مثال دسترسی به اسکنر در یک برنامهی وب متداول بیمعنا است. اما سیلورلایت 4 در حالت اجرای در خارج از مرورگر امکان تعامل با اشیاء COM را نیز دارد.
4- برنامهی وب شما نیاز است تا مدت زمان زیادی فعال باقی بماند.
یک برنامه دریافت ایمیل یا یک برنامه مونیتورینگ را در نظر بگیرید. اینگونه برنامهها باید مرتبا بدون نیاز به دخالت کاربر، فعال باقی بمانند و با سرور ارتباط داشته باشند. نوشتن اینگونه برنامهها با HTML و جاوا اسکریپت و فناوریهای مشابه واقعا مشکل بوده و نیاز به دانش فنی بالایی دارند. اما این مساله و حیات یک برنامه سیلورلایت تا زمانیکه مرورگر بسته نشده است جزو خواص اولیه اینگونه برنامهها است.
5- از مشکلات مدیریت حالت در برنامههای متداول وب به تنگ آمدهاید.
اگر برای مثال برنامه نویس ASP.NET باشید حتما با مباحث State management آشنایی دارید (از سشن و کوکی گرفته تا ViewState (ایی که همه به نحوی قصد کوچک کردن آنرا دارند!) و غیره). تمام اینها هم برای این است که بتوان تجربهی کاری برنامههای دسکتاپ را در محیط مرورگرها شبیه سازی کرد. این مشکلات در سیلورلایت حل شده است. یک برنامهی سیلورلایت State full است نه Stateless . همچنین اگر از حافظهای هم استفاده میکند این مورد در سمت کاربر است و نه سمت سرور و نه منقضی شدن زود هنگام سشنها و صدها ترفند برای مقیاس پذیری همین مسالهی بسیار کوچک با تعداد کاربران بالا در برنامههای متداول وب.
به عبارتی تصور کنید که برنامهی دسکتاپ سالهای قبل شما هم اکنون داخل مرورگر دارد اجرا میشود و چیزی به نام وب سرور وجود ندارد که پس از نمایش صفحهی وب شما، کلیهی اشیاء مرتبط با آنرا در سمت سرور تخریب کند چون باید پاسخگوی کاربران همزمان بیشماری باشد و منابع سرور هم محدود است. (سیلورلایت یک فناوری سمت کاربر است. بنابراین وب سرور صرفا نقش توزیع آنرا به عهده دارد یا حداکثر ارائهی یک وب سرویس جهت تعاملات بعدی مانند کار با بانک اطلاعاتی)
6- نیاز دارید تا برنامهی وب شما تحت تمام مرورگرها به یک شکل به نظر برسد و همچنین رفتار یکسانی هم داشته باشد.
هیچ وقت روزی را فراموش نمیکنم که حین پرداخت الکترونیکی بانک XYZ به کمک مرورگر فایرفاکس، دکمهی پرداخت در مرحلهی آخر، کار نمیکرد! هر چقدر روی آن کلیک میکردم اتفاقی نمیافتاد! تراکنش برگشت خورد و همین خرید ساده با مرورگر IE به سادگی انجام شد.
با سیلورلایت این مشکلات را نخواهید داشت زیرا کار نمایش برنامه شما توسط افزونهی مربوطه صورت میگیرد و این افزونه مستقل است از نوع مرورگر شما.
7- نیاز است برنامهی وب شما در حالت آفلاین هم کار کند.
برنامههای سیلورلایت تنها زمانیکه نیاز به دریافت یا ثبت اطلاعاتی از سرور داشته باشند، باید آنلاین باشند. همچنین این برنامهها دسترسی به مفهوم جدیدی به نام Isolated Storage دارند که در آن میتوان اطلاعات را به ازای هر کاربر آن هم با ضریب امنیتی بالا بر روی هارد شخص ذخیره کرد و زمان آنلاین شدن برنامه آنها را به سرور انتقال داد.
8- برنامه وب شما نیاز است تا با فایلهای مالتی مدیا تعامل داشته و آنها را پخش کند.
حتی تگ Video در HTML5 نیز به پای تواناییهای مالتی مدیا در Silverlight مانند smooth streaming, multicasting, editing, video brushes نمیرسد. برای مثال با استفاده از video brushes میتوان یک فایل ویدیویی در حال پخش را بر روی یک وجه یک شیء در حال پویانمایی نقاشی و نمایش داد.
9- نیاز به پشتیبانی از multi-touch در برنامهی وب شما وجود دارد.
برخلاف HTML ، تعاملات multi-touch در Silverlight میسر است.
10- نیاز به ایجاد برنامههای بازی تحت وب دارید.
به طور قطع میتوان بازییهایی در حد Pong را با جاوا اسکریپت هم ایجاد کرد، اما اگر نیاز به تولید بازیهایی جدیتر وجود داشت برای مثال انتقال بازی Quake به محیط وب، Silverlight در این زمینه هم حرفهای زیادی برای گفتن دارد (+).
11- نیاز به تولید برنامهی دسکتاپ چند سکویی دارید.
سیلورلایت هم اکنون تحت ویندوز، MAC OS-X ، لینوکس و ... پشتیبانی میشود (+). همچنین برنامههای سیلورلایت قابلیت اجرای در خارج از مرورگر را هم دارند.
با سیلورلایت دیگر نیازی نخواهد بود تا کاربران لینوکسی ابتدا Wine را نصب کنند تا بتوانند از یک برنامهی ویندوزی که انتقال پذیر نیست در لینوکس هم بتوانند استفاده کنند؛ چون پروژهی مون لایت لینوکسی برای این منظور مهیا است.
12- نیاز به تولید برنامههای تحت وب سریع و با کارآیی بالا دارید.
فایلهای نهایی Silverlight با توجه به ماهیت کامپایل شدهی آنها به طور قطع از کدهای جاوا اسکریپتی سمت کلاینت که باید توسط مرورگر تفسیر و پردازش شوند (و هر کدام هم از موتور خاص خودشان استفاده میکنند)، سریعتر اجرا میشوند (+).
13- از پیچیدگیهای پیاده سازی برنامههای متداول وب خسته شدهاید.
هنوز هم با تمام پیشرفتهای حاصل، تولید برنامههای وب پیشرفته مشکل است. از یک طرف ناسازگاری یک سری از مرورگرها با یک سری از قابلیتها را باید در نظر داشت، تا فراگیری فریم ورکهای Ajax و غیره تا مشکل بودن طراحی کنترلهای جدید فراتر از آن چیزی که HTML استاندارد ارائه میدهد. بله، به طور قطع دانش فنی بالایی در این زمینه در طی سالیان تولید شده است، اما باز هم فراگیری و تسلط به آنها زمان قابل توجهی را طلب میکند.
در سیلورلایت کلیه تعاملات با شبکه به صورت پیش فرض غیرهمزمان است (همان ایدهی اصلی Ajax) همچنین با توجه به state full بودن اینگونه برنامهها، عملا برنامه نویسها بدون درگیر شدن با مفاهیم اجکسی و مدیریت حالت، برنامهی پیشرفتهی وبی را در مدت زمان کوتاهی تولید کردهاند و این برنامه در تمام مرورگرهایی که قابلیت بارگذاری افزونهی سیلورلایت را دارند به یک شکل و کیفیت اجرا میشود.
14- در زمینه میزان مصرف پهنای باند ملاحظاتی ویژهای وجود دارد.
یک برنامهی سیلورلایت تنها یکبار باید دریافت شود. پس از آن در سمت کاربر کش خواهد شد (تا زمان به روز رسانی بعدی برنامه در سرور). همین مساله در دفعات بعدی مراجعه کاربر به سایت نقش قابل توجهی را در کاهش میزان مصرف پهنای باند (یا به قولی میزان کمتر data transfer) کلی دارد.
15- فرصت کافی برای فراگیری انبوهی از فناوریهای مختلف را ندارید!
بله! برای ایجاد یک برنامهی تحت وب که کاربر آن پس از مشاهده بگوید WOW نیاز است به HTML ، JS ، CSS ، AJAX ، یکی از فناوریهای سمت سرور و ... مسلط بود (علاوه بر اینکه باید بدانید فلان کد JS در IE کار میکند اما در فایرفاکس خیر. فایرفاکس فلان قسمت CSS را پشتیبانی میکند اما IE خیر! و ...).
اما برای استفاده از سیلورلایت فقط کافی است به XAML و یکی از زبانهای دات نت مانند سی شارپ یا VB.NET مسلط باشید (البته هیچ وقت از دست ASP.NET خلاص نخواهید شد! حداقل در حد راه اندازی یک وب سرویس یا مفاهیم امنیتی آن).
این مورد خصوصا برای افرادی که برنامه نویس دسکتاپ هستند اما علاقمندند تا برنامهی وب نیز تولید کنند بسیار مهم است. با حداقل آموزش میتوانند تواناییهای خود را به وب نیز گسترش دهند. علاوه بر آن عمدهی دانش Silverlight شما جهت تولید برنامههای WPF (با توجه به اینکه Silverlight فرزند WPF محسوب میشود) یا Windows phone 7 و غیره نیز میتواند بکار گرفته شود.
16- نیاز به اجرای کدهای چند ریسمانی در سمت کاربر دارید.
تا این لحظه پشتیبانی رسمی از مباحث چند ریسمانی در JavaScript و استانداردهای مرتبط با آن وجود ندارد. Silverlight به اکثر امکانات Threading موجود در دات نت فریم ورک دسترسی داشته و دانش فعلی شما قابل انتقال است.
و دست آخر باید به نکته اشاره کرد که هدف از Silverlight ساخت وب سایت معمولی نیست. این نوع کارها را با همان ابزارهای متداول انجام دهید. هدف اصلی آن ساخت برنامه است (Application در مقابل Web site). مشتریهای اصلی این نوع برنامهها هم بیشتر سازمانها و اینترانتهای پر سرعت و بستهی آنها هستند که نه نگران حجم افزونهی سیلورلایت هستند و نه مشکلی با حجم برنامهی سیلورلایت شما در یک شبکهی داخلی پر سرعت دارند.
مدل EAV چیست؟
اون قدر تمرکز نکنیم روی مدل دیتابیس فیسبوک که از دیتابیسهای ساده مورد نیاز نرمافزارهای خودمان غافل شده و قدرت کار بهینه روی آن را از دست بدهیم. مثال میزنم. در جمعهای برنامهنویسی چه در دانشگاهها، چه در شرکتها چه در فضای اینترنت وقتی صحبت از دیتابیس میشود همه طوری حرف میزنند که انگار طراحی دیتابیس فیسبوک و امثال آن را فوت آب هستند اما وقتی پای عمل میرسد در عوض کردن دیتابیس یک نرمافزار کوچک از MS SQL به Express یا CE یا SQLite از زمین تا آسمان مشکل دارند و نرمافزاری که تولید کردهاند فقط روی یکی دو مدل ویندوز با یک سری configهای خیلی محدود قابل اجرا هستند. بخشی از این مشکل به خاطر عدم تمرکز روی کاربردهای رایج و همه روزه از دیتابیس، کامپیوتر، نرمافزار، فناوری و غیره است.
البته و صد البته مطالعه و بررسی مواردی که حتی در ایران قابلیت اجرا ندارند خیلی هم خوب است و دیدگاههای جدیدی به آدم میدهد. منتها اول باید به عنوان یک مهندس نرمافزار خوب به وظایفمان که تولید و راهبری سیستمهای نرمافزاری در حیطه کشور است عمل کنیم سپس به سراغ چنین مباحثی برویم.
ذهن من پر مثال است. در حالی که استاندارد ساختمان سازی در ایران بسیار پایین است و عمر ساختمان در حد ۳۰ سال است (یک چندم استاندارد جهانی)، مقاومت زیادی در برابر زلزله ندارند و هزار ایراد دیگر، آن وقت میایم دست به ساختن برج میلاد میزنیم. اگر واقعاً توان مهندسی داریم اول آن را جاهایی که ضروریتر است مصرف کنیم سپس جاهایی که اسم گنده دارند و برایمان «رزومه» میشود.