سلام؛ من اون قسمتی رو که در مورد OnMessageReceived توضیح دادین رو متوجه نشدم. الان من لاگین کردم و توکن رو گرفتم طبق فرمایشات شما. اما نمیخوام از ajax استفاده کنم. پس نمیتونم طبق الگو به اون صورت که در مخزن اومده header رو پر کنم. الان چجوری میتونم در پیمایش بین اکشنها و فرستادن request بدون ajax، هدر و HttpContext.user رو پر کنم؟ اگر مثالی یا توضیح بیشتری دارین ممنون میشم ازتون
در مطلب قبلی قراردادهای کوئری نویسی در OData و WCF Data Service - قسمت اول با قراردادهای کوئری نویسی آشنا شدید در این مطلب به جزئیات بیشتر این قراردادها میپردازیم.
ادامه دارد...
عمگرهای منطقی
در OData نه عملگر منطقی داریم که امکان مقایسه منطقی در عباراتهای شرطی را در اختیارمان قرار میدهد.
- eq عملگر برابری
- ne عملگر مخالف
- lt عملگر کوچکتری
- le عملگر کوچکتر یا مساوی
- gt عملگر بزرگنری
- ge عملگر بزرگتر یا مساوی
- and
- or
- not
پنج عمگر ریاضی وجود دارد که امکان انجام عملیات ریاضی در کوئری را میسر میسازد.
- add جمع دو عملوند
- sub تفریق دو عملوند
- mul ضرب دو عملوند
- div تقیسم دو عملوند
- mod باقیمانده تقسیم دو عملوند
در آخر () برای گروه بنده و اولویت دهی عبارات کاربرد دارد.
توابع عبارتهای کوئری نویسی
در OData چهار دسته توابع داریم
- String Functions در جدول زیر این توابع با توضیح آن آورده شده است:
آیا رشته p0 شامل رشته p1 هست؟
مثال:http://services.odata.org//Northwind.svc/Customers?$filter=substringof('Alfreds', CompanyName) eq true
شرح: مشتریانی که نام شرکت آنها شامل رشته Alfreds باشدbool substringof(string p0, string p1)
آیا رشته p0 با رشته p1 پایان مییابد؟
مثال:http://services.odata.org/Northwind/Northwind.svc/Customers?$filter=endswith(CompanyName, 'Futterkiste')
شرح: مشتریانی که نام شرکت آنها با رشته FutterKiste پایان مییابدbool endswith(string p0, string p1) آیا رشته p0 با رشته p1 آغاز میشود؟
مثال:http://services.odata.org/Northwind.svc/Customers?$filter=startswith(CompanyName, 'Alfr')
شرح: مشتریانی که نام شرکت آنها با رشته Alfer آغاز مییابدboolstartswith(string p0, string p1) محاسبه طول رشته دریافتی.
مثال:http://services.odata.org/Northwind/Northwind.svc/Customers?$filter=length(CompanyName) eq 19
شرح: مشتریانی که طول نام شرکت آنها برابر 19 باشدint length(string p0) برگشت اندیس رشته وروری
مثال:http://services.odata.org/Northwind.svc/Customers?$filter=indexof(CompanyName, 'lfreds') eq 1
شرح: مشتریانی که نام شرکت آنها با رشته lfreds که از کارکتر دوم شروع مییابدint indexof(string arg) جایگزینی یک رشته در رشته دیگر
مثال:http://services.odata.org/Northwind.svc/Customers?$filter=replace(CompanyName, ' ', '') eq 'AlfredsFutterkiste'
شرح: مشتریانی که نام شرکت آنها بدون فاصله برابر AlfredsFutterkiste باشد با پرکردن فاصله با جای خالیstring replace(string p0, string find, string replace)
برگرداندن رشته ای از رشته دیگر از شماره اندیس ورودی یا از شماره اندیس تا طول رشته ورودی
مثال:http://services.odata.org/Northwind.svc/Customers?$filter=substring(CompanyName, 1) eq 'lfreds Futterkiste
شرح: مشتریانی که نام شرکت آنها از کاراکتر دوم برابر lfreds Futterkiste باشد
'http://services.odata.org/Northwind.svc/Customers?$filter=substring(CompanyName, 1,2) eq 'lfstring substring(string p0, int pos)
string substring(string p0, int pos, int length)برگرداندن رشته ورودی با کارکتر بزرگ
برگرداندن رشته ورودی با کاراکتر کوچکstring tolower(string p0)
string toupper(string p0)حذف کارکترهای Whitespace از دو طرف رشته string trim(string p0) الحاق رشته به هم string concat(string p0, string p1)
- Date Functions
برگرداندن سال تاریخ ورودی
مثال:http://services.odata.org/Northwind.svc/Employees?$filter=year(BirthDate) eq 1971 نint year(DateTimep0)
برگرداندن ماه تاریخ ورودی
مثال:http://services.odata.org/Northwind/Northwind.svc/Employees?$filter=month(BirthDate) eq 5int month(DateTimep0) برگرداندن روز تاریخ ورودی
برگرداندن تعداد روز فاصله زمانی
مثال: http://services.odata.org/Northwind.svc/Employees?$filter=day(BirthDate) eq 8int days(DateTimep0)
int day(DateTimep0)
برگرداندن ساعت تاریخ ورودی
مثال:http://services.odata.org/Northwind.svc/Employees?$filter=hour(BirthDate) eq 4int hour(DateTimep0)
برگرداندن دقیقه تاریخ ورودی
مثال:http://services.odata.org/Northwind.svc/Employees?$filter=minute(BirthDate) eq 40int minute(DateTimep0)
int minutes(DateTimep0)
برگرداندن ثانبه تاریخ ورودی
مثال:http://services.odata.org/Northwind.svc/Employees?$filter=second(BirthDate) eq 40int second(DateTimep0)
- Math Functions
برگرداندن سقف عدد ورودی
مثال:http://services.odata.org/Northwind.svc/Orders?$filter=ceiling(Freight) eq 32double ceiling(double p0)
decimal ceiling(decimal p0)برگرداندن کف عدد ورودی
مثال:http://services.odata.org/Northwind.svc/Orders?$filter=floor(Freight) eq 32double floor(double p0)
decimal floor(decimal p0)گردن کردن عدد ورودی
مثال:ttp://services.odata.org/Northwind.svc/Orders?$filter=round(Freight) eq 32double round(double p0)
decimal round(decimal p0)
- Type Functions
برگرداندن نوع داده وروری
مثالhttp://services.odata.org/Northwind.svc/Orders?$filter=isof(Customer, NorthwindModel.MVPCustomer)
شرح: سفارشاتی که نوع مشتری آنها برابر MVPCustomer باشدboolisof(type p0)
boolisof(expression p0, type p1)تبدیل نوع داده ورودی
<p0> cast(type p0)
< p1> cast(expression p0, type p1
در آخر چند نکته
- برای استفاده از رشتهها در عبارات از ' تک کوتشن استفاده نمایید
- برای دستیابی به مقادیر پروپرتیها از value$ استفاده نمایید
- برای دستیابی به آدرس روابطهای یک موجودیت از links$ استفاده نمایید
مثال:http://services.odata.org/OData/OData.svc/Categories(1)/$links/Products - select$ برای محدود کردن پروپرتیهای یک موجودیت استفاده میشود
مثال:http://services.odata.org/OData/OData.svc/Products?$select=Price,Name - از ستاره برای دستیابی به همه پروپرتیهای یک موجودیت میتوان استفاده نمود
مثال:http://services.odata.org/OData/OData.svc/Products?$select=*
C# 7 به همراه تغییرات قابل توجهی در مورد نحوهی دریافت خروجی از متدها است که نمونههایی از آنها را مانند tuples و out variable، پیشتر بررسی کردیم. در ادامه تغییرات جدید دیگری را به نام ref locals و ref returns نیز بررسی خواهیم کرد و هدف از آن، کاهش تعداد بار کپی کردن مقادیر و یا اعمال dereferencing جهت بالا بردن کارآیی برنامه هستند.
انتقال توسط مقدار
اگر پارامتری به صورت value type تعریف شود، این مقدار درون متد، ایجاد شده و حافظهای به آن اختصاص داده میشود و سپس در انتهای متد تخریب خواهد شد. بنابراین تغییری در مقدار آن، سبب انعکاس آن به فراخوان متد، نخواهد شد.
در این مثال متد PassByValue تنها یک کپی از مقدار متغیر a را دریافت میکند. بنابراین هر تغییری که درون متد PassByValue بر روی این مقدار دریافتی رخ دهد، به فراخوان آن منتقل نخواهد شد.
انتقال توسط ارجاع
برای بازگشت مقدار تغییر داده شدهی توسط یک متد، میتوان یک نوع خروجی را برای آن تعریف کرد. راه دیگر آن تعریف یک پارامتر توسط واژهی کلیدی ref است. پارامتری که به این روش تعریف شود، هم ارسال کنندهی مقدار و هم دریافت کنندهی تغییرات خواهد بود.
در این مثال متغیر x به مقدار متغیر a اشاره میکند. بنابراین هر تغییری که بر روی آن صورت گیرد، به متغیر a هم اعمال و منعکس خواهد شد.
متغیرهای out
با استفاده از واژهی کلیدی ref، میتوان یک مقدار را هم به تابع ارسال کرد و هم از آن دریافت نمود. اما اگر تنها قرار است مقداری از تابع بازگشت داده شود، میتوان از متغیرهای out استفاده کرد.
در حالت استفادهی از واژهی کلیدی out، نیازی به مقدار دهی اولیهی متغیر ارسالی به متد نیست و در اینجا روش جدید تعریف متغیرهای out را در C# 7 نیز مشاهده میکنید که نیازی نیست تا ابتدا int a را تعریف کرد و سپس در متد Out آنرا فراخوانی نمود. میتوان کل عملیات را به صورت خلاصه در یک سطر ذکر کرد.
البته اگر تنها قرار است یک مقدار را از یک متد دریافت کنیم، بهتر است نوع خروجی متد را مشخص کرد و از آن استفاده نمود؛ بجای استفادهی از متغیرهای out. یک نمونه کاربرد مفید متغیرهای out در خود فریم ورک و توسط متد TryParse وجود دارد:
Ref Locals در C# 7
در C# 7، امکان تعریف متغیرهای محلی از نوع ref نیز وجود دارد:
در اینجا متغیر x1 دارای ارجاعی است به متغیر x. بنابراین تغییر مقدار x1، به متغیر x نیز منعکس خواهد شد.
باید دقت داشت که نمیتوان یک مقدار را به یک ref variable نسبت داد:
به این ترتیب امکان اشتباه گرفتن بین value variables و reference variables توسط کامپایلر گوشزد خواهد شد:
Ref Returns در C# 7
در C# 7، واژهی کلیدی ref را به همراه نوع خروجی نیز میتوان بکار برد:
در این مثال ارجاعی به اولین عضو آرایهی تعریف شده، به عنوان خروجی متد بازگشت داده میشود. همچنین میتوان این کد را به صورت سادهتر ذیل نیز نوشت:
باید دقت داشت که یک متغیر int محلی را نمیتوان به صورت ref بازگشت داد. علت اینجا است که متغیر int یک value type است و در انتهای متد تخریب خواهد شد. بنابراین امکان بازگشت آن به صورت ref میسر نیست. اما آرایهها reference type بوده و بر روی heap تشکیل میشوند. در این حالت متغیر int داخل آرایه را میتوان به صورت ref بازگشت داد.
هرچند امکان بازگشت یک متغیر محلی int به صورت ref وجود ندارد، اما اگر این متغیر به صورت ref به تابع ارسال شده باشد، این امکان میسر است:
چند نکته: امکان تعریف فیلد ref و یا خاصیت get;set دار از نوع ref وجود ندارد. اما تعریف خواصی که یک ref را بازگشت میدهند، میسر هستند:
مزیت کار با ref returns
ref returnها شاید آنچنان در کدهای روزمرهی #C بکارگرفته نشوند، اما نیاز به کدهای unsafe و کار مستقیم با pointers را به حداقل میرسانند و به آن میتوان لقب safe pointer را اطلاق کرد؛ از این جهت که این کد هنوز هم یک managed code است و نه یک unsafe code.
مهمترین مزیت این قابلیت جدید را در قطعه کد فوق ملاحظه میکنید. در طراحی بازیها عموما استفادهی از آرایههای بزرگ از پیش تخصیص داده شدهی structها بسیار مرسوم است (چون میزان مصرف حافظهی کمتری را نسبت به نوعهای ارجاعی دارند و فشار کمتری را به GC وارد میکنند). اکنون با معرفی این قابلیت، دیگر نیازی نیست تا مدام آرایههای بزرگی از structها را از قسمتی به قسمت دیگر کپی کرد و سپس بر روی عناصری از آنها عملیاتی را انجام داد و مجددا این حاصل را به مکان مدنظر کپی کرد. در اینجا بدون کپی کردن value types میتوان با ایجاد ارجاعی به آنها، تغییرات مدنظر را به آنها اعمال کرد.
انتقال توسط مقدار
اگر پارامتری به صورت value type تعریف شود، این مقدار درون متد، ایجاد شده و حافظهای به آن اختصاص داده میشود و سپس در انتهای متد تخریب خواهد شد. بنابراین تغییری در مقدار آن، سبب انعکاس آن به فراخوان متد، نخواهد شد.
static void PassByValueSample() { int a = 1; PassByValue(a); Console.WriteLine($"after the invocation of {nameof(PassByValue)}, {nameof(a)} = {a}"); } static void PassByValue(int x) { x = 2; }
انتقال توسط ارجاع
برای بازگشت مقدار تغییر داده شدهی توسط یک متد، میتوان یک نوع خروجی را برای آن تعریف کرد. راه دیگر آن تعریف یک پارامتر توسط واژهی کلیدی ref است. پارامتری که به این روش تعریف شود، هم ارسال کنندهی مقدار و هم دریافت کنندهی تغییرات خواهد بود.
static void PassByReferenceSample() { int a = 1; PassByReference(ref a); Console.WriteLine($"after the invocation of {nameof(PassByReference)}, {nameof(a)} = {a}"); } static void PassByReference(ref int x) { x = 2; }
متغیرهای out
با استفاده از واژهی کلیدی ref، میتوان یک مقدار را هم به تابع ارسال کرد و هم از آن دریافت نمود. اما اگر تنها قرار است مقداری از تابع بازگشت داده شود، میتوان از متغیرهای out استفاده کرد.
static void OutSample() { Out(out int a); Console.WriteLine($"after the invocation of {nameof(Out)}, {nameof(a)} = {a}"); } static void Out(out int x) { x = 2; }
البته اگر تنها قرار است یک مقدار را از یک متد دریافت کنیم، بهتر است نوع خروجی متد را مشخص کرد و از آن استفاده نمود؛ بجای استفادهی از متغیرهای out. یک نمونه کاربرد مفید متغیرهای out در خود فریم ورک و توسط متد TryParse وجود دارد:
if (int.TryParse("42", out var result)) { Console.WriteLine($"the result is {result}"); }
Ref Locals در C# 7
در C# 7، امکان تعریف متغیرهای محلی از نوع ref نیز وجود دارد:
int x = 3; ref int x1 = ref x; x1 = 2; Console.WriteLine($"local variable {nameof(x)} after the change: {x}");
باید دقت داشت که نمیتوان یک مقدار را به یک ref variable نسبت داد:
ref int i = sequence.Count();
ref int number1 = null; // ERROR ref int number2 = 42; // ERROR
Ref Returns در C# 7
در C# 7، واژهی کلیدی ref را به همراه نوع خروجی نیز میتوان بکار برد:
static ref int ReturnByReference() { int[] arr = { 1 }; ref int x = ref arr[0]; return ref x; }
static ref int ReturnByReference2() { int[] arr = { 1 }; return ref arr[0]; }
هرچند امکان بازگشت یک متغیر محلی int به صورت ref وجود ندارد، اما اگر این متغیر به صورت ref به تابع ارسال شده باشد، این امکان میسر است:
static ref int ReturnByReference3(ref int x) { x = 2; return ref x; }
چند نکته: امکان تعریف فیلد ref و یا خاصیت get;set دار از نوع ref وجود ندارد. اما تعریف خواصی که یک ref را بازگشت میدهند، میسر هستند:
class Thing1 { ref string _Text1; /* Error */ ref string Text2 { get; set; } /* Error */ string _text = "Text"; ref string Text3 { get { return ref _text; } } // Properties that return a reference are allowed }
مزیت کار با ref returns
ref returnها شاید آنچنان در کدهای روزمرهی #C بکارگرفته نشوند، اما نیاز به کدهای unsafe و کار مستقیم با pointers را به حداقل میرسانند و به آن میتوان لقب safe pointer را اطلاق کرد؛ از این جهت که این کد هنوز هم یک managed code است و نه یک unsafe code.
private MyBigStruct[] array = new MyBigStruct[10]; private int current; public ref MyBigStruct GetCurrentItem() { return ref array[current]; }
در EF Code first برای ایجاد UNIQUE INDEX ویژگی یا تنظیمات Fluent API خاصی درنظر گرفته نشده است و میتوان از همان روشهای متداول اجرای مستقیم کوئری SQL بر روی بانک اطلاعاتی جهت ایجاد UNIQUE INDEXها کمک گرفت:
و این کل کاری است که باید در متد Seed کلاس مشتق شده از DbMigrationsConfiguration انجام شود. مثلا:
روش فوق کار میکند اما آنچنان مناسب نیست؛ چون به صورت strongly typed تعریف نشده است و اگر نام جداول یا فیلدها را بعدها تغییر دادیم، به مشکل برخواهیم خورد و کامپایلر خطایی را صادر نخواهد کرد؛ چون table1 و field1 در اینجا به صورت رشته تعریف شدهاند.
برای حل این مشکل و تبدیل کدهای فوق به کدهایی Refactoring friendly، نیاز است نام جدول به صورت خودکار از DbContext دریافت شود. همچنین نام خاصیت یا فیلد نیز به صورت strongly typed قابل تعریف باشد.
کدهای کامل نمونه بهبود یافته را در ذیل مشاهده میکنید:
توضیحات
متد GetTableName ، به کمک SQL تولیدی حین تعریف جدول متناظر با کلاس جاری، نام جدول را با استفاده از عبارات باقاعده جدا کرده و باز میگرداند. به این ترتیب به دقیقترین نامی که واقعا جهت تولید جدول مورد استفاده قرار گرفته است خواهیم رسید.
در مرحله بعد آن، همان متد createUniqueIndex ابتدای بحث را ملاحظه میکنید. در اینجا جهت حفظ سازگاری بین SQL Server کامل و SQL CE از UNIQUE CONSTRAINT استفاده شده است که همان کار ایجاد ایندکس منحصربفرد را نیز انجام میدهد. به علاوه مزیت دیگر آن امکان دسترسی به تعاریف قید اضافه شده توسط view ایی به نام INFORMATION_SCHEMA.TABLE_CONSTRAINTS است که در نگارشهای مختلف SQL Server به یک نحو تعریف گردیده و قابل دسترسی است. از این view در متد hasUniqueIndex جهت بررسی تکراری نبودن UNIQUE CONSTRAINT در حال تعریف، استفاده میشود. اگر این قید پیشتر تعریف شده باشد، دیگر سعی در تعریف مجدد آن نخواهد شد.
متد CreateUniqueIndex تعریف شده در انتهای کلاس فوق، امکان دریافت نام خاصیتی از TEntity را به صورت strongly typed میسر میسازد.
اینبار برای تعریف یک قید و یا ایندکس منحصربفرد بر روی خاصیتی مشخص در متد Seed، تنها کافی است بنویسیم:
در اینجا دیگر از رشتهها خبری نبوده و حاصل نهایی Refactoring friendly است. به علاوه نام جدول را نیز به صورت خودکار از context استخراج میکند.
public static void CreateUniqueIndex(this DbContext context, string tableName, string fieldName) { context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX [IX_Unique_" + tableName + "_" + fieldName + "] ON [" + tableName + "]([" + fieldName + "] ASC);"); }
public class MyDbMigrationsConfiguration : DbMigrationsConfiguration<MyContext> { public BlogDbMigrationsConfiguration() { AutomaticMigrationsEnabled = true; AutomaticMigrationDataLossAllowed = true; } protected override void Seed(MyContext context) { CreateUniqueIndex(context, "table1", "field1"); base.Seed(context); } }
برای حل این مشکل و تبدیل کدهای فوق به کدهایی Refactoring friendly، نیاز است نام جدول به صورت خودکار از DbContext دریافت شود. همچنین نام خاصیت یا فیلد نیز به صورت strongly typed قابل تعریف باشد.
کدهای کامل نمونه بهبود یافته را در ذیل مشاهده میکنید:
using System; using System.Data.Entity; using System.Data.Entity.Infrastructure; using System.Data.Objects; using System.Linq; using System.Linq.Expressions; using System.Text.RegularExpressions; namespace General { public static class ContextExtensions { public static string GetTableName<T>(this DbContext context) where T : class { ObjectContext objectContext = ((IObjectContextAdapter)context).ObjectContext; return objectContext.GetTableName<T>(); } public static string GetTableName<T>(this ObjectContext context) where T : class { var sql = context.CreateObjectSet<T>().ToTraceString(); var regex = new Regex("FROM (?<table>.*) AS"); var match = regex.Match(sql); string table = match.Groups["table"].Value; return table .Replace("`", string.Empty) .Replace("[", string.Empty) .Replace("]", string.Empty) .Replace("dbo.", string.Empty) .Trim(); } private static bool hasUniqueIndex(this DbContext context, string tableName, string indexName) { var sql = "SELECT count(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS where table_name = '" + tableName + "' and CONSTRAINT_NAME = '" + indexName + "'"; var result = context.Database.SqlQuery<int>(sql).FirstOrDefault(); return result > 0; } private static void createUniqueIndex(this DbContext context, string tableName, string fieldName) { var indexName = "IX_Unique_" + tableName + "_" + fieldName; if (hasUniqueIndex(context, tableName, indexName)) return; var sql = "ALTER TABLE [" + tableName + "] ADD CONSTRAINT [" + indexName + "] UNIQUE ([" + fieldName + "])"; context.Database.ExecuteSqlCommand(sql); } public static void CreateUniqueIndex<TEntity>(this DbContext context, Expression<Func<TEntity, object>> fieldName) where TEntity : class { var field = ((MemberExpression)fieldName.Body).Member.Name; createUniqueIndex(context, context.GetTableName<TEntity>(), field); } } }
توضیحات
متد GetTableName ، به کمک SQL تولیدی حین تعریف جدول متناظر با کلاس جاری، نام جدول را با استفاده از عبارات باقاعده جدا کرده و باز میگرداند. به این ترتیب به دقیقترین نامی که واقعا جهت تولید جدول مورد استفاده قرار گرفته است خواهیم رسید.
در مرحله بعد آن، همان متد createUniqueIndex ابتدای بحث را ملاحظه میکنید. در اینجا جهت حفظ سازگاری بین SQL Server کامل و SQL CE از UNIQUE CONSTRAINT استفاده شده است که همان کار ایجاد ایندکس منحصربفرد را نیز انجام میدهد. به علاوه مزیت دیگر آن امکان دسترسی به تعاریف قید اضافه شده توسط view ایی به نام INFORMATION_SCHEMA.TABLE_CONSTRAINTS است که در نگارشهای مختلف SQL Server به یک نحو تعریف گردیده و قابل دسترسی است. از این view در متد hasUniqueIndex جهت بررسی تکراری نبودن UNIQUE CONSTRAINT در حال تعریف، استفاده میشود. اگر این قید پیشتر تعریف شده باشد، دیگر سعی در تعریف مجدد آن نخواهد شد.
متد CreateUniqueIndex تعریف شده در انتهای کلاس فوق، امکان دریافت نام خاصیتی از TEntity را به صورت strongly typed میسر میسازد.
اینبار برای تعریف یک قید و یا ایندکس منحصربفرد بر روی خاصیتی مشخص در متد Seed، تنها کافی است بنویسیم:
context.CreateUniqueIndex<User>(x=>x.Name);
یکی از روشهای تهیهی برنامههای چند مستاجری، ایجاد بانکهای اطلاعاتی مستقلی به ازای هر مشتری است؛ یا نمونهی دیگر آن، برنامههایی هستند که اطلاعات هر سال را در یک بانک اطلاعاتی جداگانه نگهداری میکنند. در ادامه قصد داریم، نحوهی کار با این بانکهای اطلاعاتی را به صورت همزمان، توسط EF Code first و در حالت استفاده از الگوی واحد کار و تزریق وابستگیها، به همراه فعال سازی خودکار مباحث migrations و به روز رسانی ساختار تمام بانکهای اطلاعاتی مورد استفاده، بررسی کنیم.
مشخص سازی رشتههای متفاوت اتصالی
فرض کنید برنامهی جاری شما قرار است از دو بانک اطلاعاتی مشخص استفاده کند که تعاریف رشتههای اتصالی آنها در وب کانفیگ به صورت ذیل مشخص شدهاند:
البته، ذکر این مورد کاملا اختیاری است و میتوان رشتههای اتصالی را به صورت پویا نیز در زمان اجرا مشخص و مقدار دهی کرد.
تغییر Context برنامه جهت پذیرش رشتههای اتصالی پویای قابل تغییر در زمان اجرا
اکنون که قرار است کاربران در حین ورود به برنامه، بانک اطلاعاتی مدنظر خود را انتخاب کنند و یا سیستم قرار است به ازای کاربری خاص، رشتهی اتصالی خاص او را به Context ارسال کند، نیاز است Context برنامه را به صورت ذیل تغییر دهیم:
در اینجا دو متد سازنده را مشاهده میکنید. سازندهی پیش فرض، از رشتهای اتصالی با نامی مساوی Sample07Context استفاده میکند و سازندهی دوم، امکان پذیرش یک رشتهی اتصالی پویا را دارد. مقدار پارامتر ورودی آن میتواند نام رشتهی اتصالی و یا حتی مقدار کامل رشتهی اتصالی باشد. حالت پذیرش نام رشتهی اتصالی زمانی مفید است که همانند مثال ابتدای بحث، این نامها را پیشتر در فایل کانفیگ برنامه ثبت کرده باشید و حالت پذیرش مقدار کامل رشتهی اتصالی، جهت مقدار دهی پویای آن بدون نیاز به ثبت اطلاعاتی در فایل کانفیگ برنامه مفید است.
یک متد دیگر هم در اینجا در انتهای کلاس به نام SetConnectionString تعریف شدهاست. از این متد در حین ورود کاربر به سایت میتوان استفاده کرد. برای مثال حداقل دو نوع طراحی را میتوان درنظر گرفت:
الف) کاربر با برنامهای کار میکند که به ازای سالهای مختلف، بانکهای اطلاعاتی مختلفی دارد و در ابتدای ورود، یک drop down انتخاب سال کاری برای او درنظر گرفته شدهاست (علاوه بر سایر ورودیهای استانداردی مانند نام کاربری و کلمهی عبور). در این حالت بهتر است متد SetConnectionString نام رشتهی اتصالی را بر اساس سال انتخابی، در حین لاگین دریافت کند که اطلاعات آن در فایل کانفیگ سایت پیشتر مشخص شدهاست.
ب) کاربر یا مشتری پس از ورود به سایت، نیاز است صرفا از بانک اطلاعاتی خاص خودش استفاده کند. بنابراین اطلاعات تعریف کاربران و مشتریها در یک بانک اطلاعاتی مجزا قرار دارند و پس از لاگین، نیاز است رشتهی اتصالی او به صورت پویا از بانک اطلاعاتی خوانده شده و سپس توسط متد SetConnectionString تنظیم گردد.
مدیریت سشنهای رشتهی اتصالی جاری
پس از اینکه کاربر، در حین ورود مشخص کرد که از چه بانک اطلاعاتی قرار است استفاده کند و یا اینکه برنامه بر اساس اطلاعات ثبت شدهی او تصمیمگیری کرد که باید از کدام رشتهی اتصالی استفاده کند، نگهداری این رشتهی اتصالی نیاز به سشن دارد تا به ازای هر کاربر متصل به سایت منحصربفرد باشد. در مورد مدیریت سشنها در برنامههای وب، از نکات مطرح شدهی در مطلب «مدیریت سشنها در برنامههای وب به کمک تزریق وابستگیها» استفاده خواهیم کرد:
در اینجا نحوهی پویا سازی تامین رشتهی اتصالی را مشاهده میکنید. در مورد اینترفیس ISessionProvider و کلاس پایه HttpSessionStateBase پیشتر در مطلب «مدیریت سشنها در برنامههای وب به کمک تزریق وابستگیها» بحث شد.
نکتهی مهم این تنظیمات، قسمت مقدار دهی سازندهی کلاس Context برنامه به صورت پویا توسط IoC Container جاری است. در اینجا هر زمانیکه قرار است وهلهای از Sample07Context ساخته شود، از سازندهی دوم آن که دارای پارامتری به نام connectionString است، استفاده خواهد شد. همچنین مقدار آن به صورت پویا از متد getCurrentConnectionString که در انتهای کلاس تعریف شدهاست، دریافت میگردد.
در این متد ابتدا مقدار HttpContext.Current بررسی شدهاست. این مقدار اگر نال باشد، یعنی برنامهی جاری یک برنامهی دسکتاپ است و مدیریت رشتهی اتصالی جاری آنرا توسط یک خاصیت Static یا Singleton تعریف شدهی در برنامه نیز میتوان تامین کرد. از این جهت که در هر زمان، تنها یک کاربر در App Domain جاری برنامهی دسکتاپ میتواند وجود داشته باشد و Singleton یا Static تعریف شدن اطلاعات رشتهی اتصالی، مشکلی را ایجاد نمیکند. اما در برنامههای وب، چندین کاربر در یک App Domain به سیستم وارد میشوند. به همین جهت است که مشاهده میکنید در اینجا از تامین کنندهی سشن، برای نگهداری اطلاعات رشتهی اتصالی جاری کمک گرفته شدهاست.
کلید این سشن نیز در این مثال مساوی CurrentConnectionStringName تعریف شدهاست. بنابراین در حین لاگین موفقیت آمیز کاربر، دو مرحلهی زیر باید طی شوند:
ابتدا باید سشن CurrentConnectionStringName به بانک اطلاعاتی انتخابی کاربر تنظیم شود. برای نمونه در این مثال خاص، از نام رشتهی اتصالی مشخص شدهی در وب کانفیگ برنامه (مثال ابتدای بحث) به نام Sample07Context استفاده شدهاست.
سپس از متد SetConnectionString برای خواندن مقدار نام مشخص شده در سشن CurrentConnectionStringName کمک گرفتهایم. هرچند سازندهی کلاس Context برنامه، هر دو حالت استفاده از نام رشتهی اتصالی و یا مقدار کامل رشتهی اتصالی را پشتیبانی میکند، اما خاصیت this.Database.Connection.ConnectionString تنها رشتهی کامل اتصالی را میپذیرد (بکار رفته در متد SetConnectionString).
تا اینجا کار پویا سازی انتخاب و استفاده از رشتهی اتصالی برنامه به پایان میرسد. هر زمانیکه قرار است Context برنامه توسط IoC Container نمونه سازی شود، به متد getCurrentConnectionString رجوع کرده و مقدار رشتهی اتصالی را از سشن تنظیم شدهای به نام CurrentConnectionStringName دریافت میکند. سپس از مقدار آن جهت مقدار دهی سازندهی دوم کلاس Context استفاده خواهد کرد.
مدیریت migrations خودکار برنامه در حالت استفاده از چندین بانک اطلاعاتی
یکی از مشکلات کار با برنامههای چند دیتابیسی، به روز رسانی ساختار تمام بانکهای اطلاعاتی مورد استفاده، پس از تغییری در ساختار مدلهای برنامه است. از این جهت که اگر تمام بانکهای اطلاعاتی به روز نشوند، کوئریهای جدید برنامه که از خواص و فیلدهای جدید استفاده میکنند، دیگر کار نخواهند کرد. پویا سازی اعمال این تغییرات را میتوان به صورت ذیل انجام داد:
نکتهی مهمی که در اینجا بکار گرفته شدهاست، مشخص سازی صریح سازندهی شیء MigrateDatabaseToLatestVersion است. به صورت معمول در اکثر برنامههای تک دیتابیسی، نیازی به مشخص سازی پارامتر سازندهی این کلاس نیست و در این حالت از سازندهی بدون پارامتر کلاس Context برنامه استفاده خواهد شد. اما اگر سازندهی آنرا مشخص کنیم، به صورت خودکار از متد سازندهای در کلاس Context استفاده میکند که پارامتر رشتهی اتصالی را به صورت پویا میپذیرد.
در این مثال خاص، متد initDatabases در حین آغاز برنامه فراخوانی شدهاست. منظور این است که اینکار در طول عمر برنامه تنها کافی است یکبار انجام شود و پس از آن است که EF Code first میتواند از رشتههای اتصالی متفاوتی که به آن ارسال میشود، بدون مشکل استفاده کند. زیرا اطلاعات نگاشت کلاسهای مدل برنامه به جداول بانک اطلاعاتی به این ترتیب است که کش میشوند و یا بر اساس کلاس Configuration به صورت خودکار به بانک اطلاعاتی اعمال میگردند.
کدهای کامل این مثال را که در حقیقت نمونهی بهبود یافتهی مطلب «EF Code First #12» است، از اینجا میتوانید دریافت کنید:
UoW-Sample
مشخص سازی رشتههای متفاوت اتصالی
فرض کنید برنامهی جاری شما قرار است از دو بانک اطلاعاتی مشخص استفاده کند که تعاریف رشتههای اتصالی آنها در وب کانفیگ به صورت ذیل مشخص شدهاند:
<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
این بخش مروری اجمالی بر الگوریتمهای موجود در Analysis Services و پارامترهای قابل تنظیم و مقدار پیش فرض هر پارامتر میباشد، به منظور بررسی بیشتر هر یک به لینکهای زیر مراجعه کنید:
(Data Mining Algorithms (Analysis Services - Data Mining
(Algorithm Parameters (SQL Server Data Mining Add-ins
1 - Microsoft Association Rules
به منظور ایجاد قوانینی که توصیف کننده این موضوع باشد که چه مواردی احتمالاً با یکدیگر در تراکنشها ظاهر میشوند، استفاده میشود.
2 - Microsoft Clustering
به منظور شناسائی روابطی که در یک مجموعه داده ممکن است از طریق مشاهده منطقی به نظر نرسد، استفاده میشود. در واقع این الگوریتم با استفاده از تکنیکهای تکرار شونده رکوردها را در خوشه هایی که حاوی ویژگیهای مشابه هستند گروه بندی میکند.
3 - Microsoft Decision Trees
مبتنی بر روابط بین ستونهای یک مجموعه داده ای باعث پیش بینی روابط مدلها میشود، که به صورت یک سری درختوار ویژگیها در آن شکسته میشوند.
به منظور انجام پیش بینی از هر دو ویژگی پیوسته و گسسته پشتیبانی میشود.
4 - Microsoft Linear Regression
چنانچه یک وابستگی خطی میان متغیر هدف و متغیرهای مورد بررسی وجود داشته باشد، کارآمدترین رابطه میان متغیر هدف و ورودیها را پیدا میکند.
به منظور انجام پیش بینی از ویژگی پیوسته پشتیبانی میکند.
5 - Microsoft Logistic Regression
به منظور تجزیه و تحلیل عواملی که در یک تصمیم گیری مشارکت دارند که پی آمد آن به وقوع یا عدم وقوع یک رویداد میانجامد از این الگوریتم استفاده میشود.
جهت انجام پیش بینی از هر دو ویژگی پیوسته و گسسته پشتیبانی میکند.
6 - Microsoft Naïve Bayes
احتمال ارتباط میان تمامی ستونهای ورودی و ستونهای قابل پیش بینی را پیدا میکند. همچنین این الگوریتم برای تولید سریع مدل کاوش به منظور کشف ارتباطات بسیار سودمند میباشد. تنها از ویژگیهای گسسته یا گسسته شده پشتیبانی میکند و با تمامی ویژگیهای ورودی به شکل مستقل رفتار میکند.
7 - Microsoft Neural Network
به منظور تجزیه و تحلیل دادههای ورودی پیچیده یا مسائل بیزنسی که برای آنها مقدار قابل توجهی داده آموزشی در دسترس میباشد اما به آسانی نمیتوان با استفاده از الگوریتمهای دیگر این قوانین را بدست آورد، استفاده میشود. با استفاده از این الگوریتم میتوان چندین ویژگی را پیش بینی نمود. همچنین این الگوریتم میتواند به منظور طبقه بندی برای ویژگیهای گسسته و ویژگیهای پیوسته رگرسیون مورد استفاده قرار گیرد.
8 - Microsoft Sequence Clustering
به منظور شناسائی ترتیب رخدادهای مشابه در یک دنباله استفاده میشود. در واقع این الگوریتم ترکیبی از تجزیه تحلیل توالی و خوشه را فراهم میکند.
9 - Microsoft Time Series
به منظور تجزیه و تحلیل دادههای زمانی (دادههای مرتبط با زمان) در یک درخت تصمیم گیری خطی استفاده میشود. الگوهای کشف شده میتوانند به منظور پیش بینی مقادیر آینده در سریهای زمانی استفاده شوند.
(Data Mining Algorithms (Analysis Services - Data Mining
(Algorithm Parameters (SQL Server Data Mining Add-ins
1 - Microsoft Association Rules
به منظور ایجاد قوانینی که توصیف کننده این موضوع باشد که چه مواردی احتمالاً با یکدیگر در تراکنشها ظاهر میشوند، استفاده میشود.
Range | Default | Parameter |
(...,1] | 200000 | MAXIMUM_ITEMSET_COUNT |
[0,500] | 3 | MAXIMUM_ITEMSET_SIZE |
(...,0.0) | 1.0 | MAXIMUM SUPPORT |
(...,...) | 999999999- | MINIMUM IMPORTANCE |
[1,500] | 1 | MINIMUM_ITEMSET_SIZE |
[0.0,1.0] | 0.4 | MINIMUM PROBABILITY |
(...,0.0] | 0.0 | MINIMUM SUPPORT |
2 - Microsoft Clustering
به منظور شناسائی روابطی که در یک مجموعه داده ممکن است از طریق مشاهده منطقی به نظر نرسد، استفاده میشود. در واقع این الگوریتم با استفاده از تکنیکهای تکرار شونده رکوردها را در خوشه هایی که حاوی ویژگیهای مشابه هستند گروه بندی میکند.
Range | Default | Parameter |
(...,0] | 10 | CLUSTER COUNT |
(...,0] | 0 | CLUSTER SEED |
1,2,3,4 | 1 | CLUSTERING METHOD |
[0,65535] | 255 | MAXIMUM_INPUT_ATTRIBUTES |
[2,65535],0 | 100 | MAXIMUM STATES |
(...,0) | 1 | MINIMUM SUPPORT |
[1,50] | 10 | MODELLING_CARDINALITY |
(...,100],0 | 50000 | SAMPLE SIZE |
(...,0) | 10 | STOPPING TOLERANCE |
3 - Microsoft Decision Trees
مبتنی بر روابط بین ستونهای یک مجموعه داده ای باعث پیش بینی روابط مدلها میشود، که به صورت یک سری درختوار ویژگیها در آن شکسته میشوند.
به منظور انجام پیش بینی از هر دو ویژگی پیوسته و گسسته پشتیبانی میشود.
Range | Default | Parameter |
(0.0,1.0) | COMPLEXITY_PENALTY | |
FORCE REGRESSOR | ||
[0,65535] | 255 | MAXIMUM_INPUT_ATTRIBUTES |
[0,65535] | 255 | MAXIMUM_OUTPUT_ATTRIBUTES |
(...,0.0) | 10.0 | MINIMUM SUPPORT |
1,3,4 | 4 | SCORE METHOD |
[1,3] | 3 | SPLIT METHOD |
4 - Microsoft Linear Regression
چنانچه یک وابستگی خطی میان متغیر هدف و متغیرهای مورد بررسی وجود داشته باشد، کارآمدترین رابطه میان متغیر هدف و ورودیها را پیدا میکند.
به منظور انجام پیش بینی از ویژگی پیوسته پشتیبانی میکند.
Range | Default | Parameter |
| FORCE REGRESSOR | |
[0,65535] | 255 | MAXIMUM_INPUT_ATTRIBUTES |
[0,65535] | 255 | MAXIMUM_OUTPUT_ATTRIBUTES |
5 - Microsoft Logistic Regression
به منظور تجزیه و تحلیل عواملی که در یک تصمیم گیری مشارکت دارند که پی آمد آن به وقوع یا عدم وقوع یک رویداد میانجامد از این الگوریتم استفاده میشود.
جهت انجام پیش بینی از هر دو ویژگی پیوسته و گسسته پشتیبانی میکند.
Range | Default | Parameter |
(0,100) | 30 | HOLDOUT_PERCENTAGE |
(...,...) | 0 | HOLDOUT SEED |
[0,65535] | 255 | MAXIMUM_INPUT_ATTRIBUTES |
[0,65535] | 255 | MAXIMUM_OUTPUT_ATTRIBUTES |
[2,65535],0 | 100 | MAXIMUM STATES |
(...,0] | 10000 | SAMPLE SIZE |
6 - Microsoft Naïve Bayes
احتمال ارتباط میان تمامی ستونهای ورودی و ستونهای قابل پیش بینی را پیدا میکند. همچنین این الگوریتم برای تولید سریع مدل کاوش به منظور کشف ارتباطات بسیار سودمند میباشد. تنها از ویژگیهای گسسته یا گسسته شده پشتیبانی میکند و با تمامی ویژگیهای ورودی به شکل مستقل رفتار میکند.
Range | Default | Parameter |
[0,65535] | 255 | MAXIMUM_INPUT_ATTRIBUTES |
[0,65535] | 255 | MAXIMUM_OUTPUT_ATTRIBUTES |
[2,65535],0 | 100 | MAXIMUM STATES |
(0,1) | 0.5 | MINIMUM_DEPENDENCY_PROBABILITY |
7 - Microsoft Neural Network
به منظور تجزیه و تحلیل دادههای ورودی پیچیده یا مسائل بیزنسی که برای آنها مقدار قابل توجهی داده آموزشی در دسترس میباشد اما به آسانی نمیتوان با استفاده از الگوریتمهای دیگر این قوانین را بدست آورد، استفاده میشود. با استفاده از این الگوریتم میتوان چندین ویژگی را پیش بینی نمود. همچنین این الگوریتم میتواند به منظور طبقه بندی برای ویژگیهای گسسته و ویژگیهای پیوسته رگرسیون مورد استفاده قرار گیرد.
Range | Default | Parameter |
(...,0] | 4.0 | HIDDEN_NODE_RATIO |
(0,100) | 30 | HOLDOUT PERCENTAGE |
(...,...) | 0 | HOLDOUT SEED |
[0,65535] | 255 | MAXIMUM_INPUT_ATTRIBUTES |
[0,65535] | 255 | MAXIMUM_OUTPUT_ATTRIBUTES |
[2,65535],0 | 100 | MAXIMUM STATES |
(...,0] | 10000 | SAMPLE SIZE |
8 - Microsoft Sequence Clustering
به منظور شناسائی ترتیب رخدادهای مشابه در یک دنباله استفاده میشود. در واقع این الگوریتم ترکیبی از تجزیه تحلیل توالی و خوشه را فراهم میکند.
Range | Default | Parameter |
(...,0] | 10 | CLUSTER COUNT |
[2,65535],0 | 64 | MAXIMUM_SEQUENCE_STATES |
[2,65535],0 | 100 | MAXIMUM STATES |
(...,0] | 10 | MINIMUM SUPPORT |
9 - Microsoft Time Series
به منظور تجزیه و تحلیل دادههای زمانی (دادههای مرتبط با زمان) در یک درخت تصمیم گیری خطی استفاده میشود. الگوهای کشف شده میتوانند به منظور پیش بینی مقادیر آینده در سریهای زمانی استفاده شوند.
Range | Default | Parameter |
[0.0,1.0] | 0.6 | AUTO_DETECT_PERIODICITY |
(1.0,...) | 0.1 | COMPLEXITY_PENALTY |
ARIMA,ARTXP,MIXED | MIXED | FORECAST METHOD |
[0,100] | 1 | HISTORIC_MODEL_COUNT |
(...,1] | 10 | HISTORIC_MODEL_GAP |
[0.0,1.0] | 1.0 | INSTABILITY_SENSITIVITY |
[...,column maximum] | 1E308+ | MAXIMUM_SERIES_VALUE |
[column minimum,...] | 1E308- | MINIMUM_SERIES_VALUE |
(...,1] | 10 | MINIMUM SUPPORT |
None,Previous,Mean | None | MISSING_VALUE_SUBSTITUTION |
{...list of integers...} | {1} | PERIODICITY_HINT |
[0.0,1.0] | 0.5 | PREDICTION SMOOTHING |
نظرسنجیها
ساعت کاری محل کار شما چگونه است؟
ساعت کاری اداری 8 تا 17 و پنج شنبه ها تا 13
همه روزه 7:30 تا 14:30
پر کردن ساعت کاری مشخص ولی با ساعت کاری دلخواه
شنبه تا چهارشنبه از 8 تا 18
همه روزه 7:30 تا 14:30
پر کردن ساعت کاری مشخص ولی با ساعت کاری دلخواه
شنبه تا چهارشنبه از 8 تا 18
فصل | عنوان | فایل مرتبط |
21 | بررسی کنترل DataForm | + |
22 | برنامه نویسی گرافیکی در Silverlight | + |
23 | آشنایی با پویا نمایی در Silverlight | + |
24 | برنامه نویسی چند ریسمانی در Silverlight | + |
25 | تعامل با کدهای HTML صفحه در Silverlight | + |
26 | استفاده از WCF RIA Services در Silverlight | + |
27 | استفاده از MEF در Silverlight 4 | + |
| منابع و مآخذ | + |
| سورس تمام مثالهای کتاب | + |
توضیحی در مورد مثالها:
تمام پوشههای مثالها دارای شماره هستند و این شمارهها متناظرند با شمارهی فضاهای نام مثالها
پیش از هرچیز به شما پیشنهاد میکنم؛ بار دیگر کد سیشارپ درس نخست را در پروژهی خود کپی کنید و سپس Publish را بزنید. پس از ارسال آن مطلب، تغییراتی در جهت بهینهسازی کد دادم که به نظرم بهتر است شما نیز در پروژهی خود به کار برید.
چرا از این نوع داده استفاده کنیم؟
نخستین پرسشی که ممکن است برای شما پیش بیاید این است که چرا بهتر است از این نوع داده استفاده کنیم. برای پاسخ به این پرسش باید راهکارهای گذشته را بررسی کنیم. معمولاً طراحان پایگاه دادهها برای استفاده از تاریخ خورشیدی، زمان را به صورت میلادی ثبت میکنند؛ سپس با یک scalar-valued function زمان درج شده را به خورشیدی تبدیل میکنند. در این صورت میتوان با یک تابع کوچک دیگر بخش مربوط به ساعت را نیز از همان ستون به دست آورد. در این صورت میتوانیم از کلیهی متدهای مربوط به DateTime در SQL از جمله افزایش و کاهش و تفاضل دو تاریخ بهره برد. برخی دیگر از طراحان، ستونی از نوع (char(10 در نظر میگیرند و تاریخ خورشیدی را به صورت دهکاراکتری در آن ذخیره میکنند. این روش هرچند نیاز به تبدیل به خورشیدی را ندارد ولی کلیهی مزایایی که در استفاده از DateTime به آنها دسترسی داریم از دست میدهیم. افزون بر این جهت نگهداری زمان باید یک فیلد دیگر از نوع کاراکتری و یا در نگارشهای نوینتر از نوع time تعریف کنیم. برخی دیگر از هر دو را در کنار هم استفاده میکنند و در واقع جهت سرعت بالاتر نمایش و بررسی دادهها از طریق محیط SQL Server از فیلد کاراکتری تاریخ خورشیدی و برای مقایسه و بدست آوردن ساعت از فیلد نوع DateTime استفاده میکنند.
از نظر فضای اشغالشده نوع DataTime، هشت بایت، smalldatetime (در صورت استفاده) 4 بایت و فیلد 10 کاراکتری تاریخ 10 بایت فضا اشغال میکند در صورتی که نوع JalaliDate با درنظر گرفتن همهی مزایای انواع دادهی استفادهشده برای تاریخ، فقط 8 بایت فضا اشغال میکند. با استفاده از این نوع به راحتی دادهی تاریخ را بر اساس تقویم ایرانی اعتبارسنجی میکنید و بخشهای مختلف زمان از سال تا ثانیه را با یک متد به دست میآورید. میتوانید به راحتی به تاریخ خود زمانی را بیفزایید یا بکاهید و در گزارشها بدون نگرانی از تبدیل درست استفاده کنید. چون کدباز است میتوانید با کمی حوصله امکانات دیگر مد نظر خود را به آن بیفزایید و از آن در SQL بهره ببرید.
چگونه این نوع داده را حذف کنم!؟
شما میتوانید به سادگی نوع دادهی ایجادشده توسط CLR را در مسیر زیر بیابید و اقدام به حذف آن نمایید:
همانطور که مشاهده میشود؛ حتی نوع دادهی سیستمی hierarchyid که جهت ساختار سلسلهمراتبی مانند چارت سازمانی یا درخت تجهیزات استفاده میشود؛ نیز یک نوع دادهی CLR است.
آیا راه دیگری نیز برای افزودن این نوع داده به SQL به جز Publish کردن وجود دارد؟
مانند بسیاری دیگر از گونههای پروژه، در اینجا نیز شما یک فایل DLL خواهید داشت. این فایل برپایهی تنظیماتی که شما در قسمت Properties پروژهی خود انجام میدهید ساخته میشود. پس از تغییر مسیر فایل DLL در دستور زیر توسط یک New Query از Database خود، آن را اجرا کنید:
همچنین در صورت ویرایشهای دوباره پروژه از دستور زیر استفاده کنید:
با استفاده از دستورهای زیر میتوانید از چگونگی درج فایلهای افزوده شده آگاه شوید:
تا اینجا SQL Server، دیالال مربوط به پروژه را شناخته است. برای تعریف نوع داده از دستور زیر بهره ببرید:
این کار همانند استفاده از گزینهی Publish در Visual Studio است.
همچنین چنانچه در SQL Server 2012 از منوی راستکلیک پایگاه دادهها روی گزینه Tasks و سپس Generate Scripts را انتخاب کنیم، از مشاهدهی سند ساخته شده، درخواهیم یافت که حتی دستورهای مربوط به ساخت اسمبلی CLR با تبدیل فایل به کد در Scripts وجود دارد و با اجرای آن در سروری دیگر، انتقال مییابد.
دنباله دارد ...
چرا از این نوع داده استفاده کنیم؟
نخستین پرسشی که ممکن است برای شما پیش بیاید این است که چرا بهتر است از این نوع داده استفاده کنیم. برای پاسخ به این پرسش باید راهکارهای گذشته را بررسی کنیم. معمولاً طراحان پایگاه دادهها برای استفاده از تاریخ خورشیدی، زمان را به صورت میلادی ثبت میکنند؛ سپس با یک scalar-valued function زمان درج شده را به خورشیدی تبدیل میکنند. در این صورت میتوان با یک تابع کوچک دیگر بخش مربوط به ساعت را نیز از همان ستون به دست آورد. در این صورت میتوانیم از کلیهی متدهای مربوط به DateTime در SQL از جمله افزایش و کاهش و تفاضل دو تاریخ بهره برد. برخی دیگر از طراحان، ستونی از نوع (char(10 در نظر میگیرند و تاریخ خورشیدی را به صورت دهکاراکتری در آن ذخیره میکنند. این روش هرچند نیاز به تبدیل به خورشیدی را ندارد ولی کلیهی مزایایی که در استفاده از DateTime به آنها دسترسی داریم از دست میدهیم. افزون بر این جهت نگهداری زمان باید یک فیلد دیگر از نوع کاراکتری و یا در نگارشهای نوینتر از نوع time تعریف کنیم. برخی دیگر از هر دو را در کنار هم استفاده میکنند و در واقع جهت سرعت بالاتر نمایش و بررسی دادهها از طریق محیط SQL Server از فیلد کاراکتری تاریخ خورشیدی و برای مقایسه و بدست آوردن ساعت از فیلد نوع DateTime استفاده میکنند.
از نظر فضای اشغالشده نوع DataTime، هشت بایت، smalldatetime (در صورت استفاده) 4 بایت و فیلد 10 کاراکتری تاریخ 10 بایت فضا اشغال میکند در صورتی که نوع JalaliDate با درنظر گرفتن همهی مزایای انواع دادهی استفادهشده برای تاریخ، فقط 8 بایت فضا اشغال میکند. با استفاده از این نوع به راحتی دادهی تاریخ را بر اساس تقویم ایرانی اعتبارسنجی میکنید و بخشهای مختلف زمان از سال تا ثانیه را با یک متد به دست میآورید. میتوانید به راحتی به تاریخ خود زمانی را بیفزایید یا بکاهید و در گزارشها بدون نگرانی از تبدیل درست استفاده کنید. چون کدباز است میتوانید با کمی حوصله امکانات دیگر مد نظر خود را به آن بیفزایید و از آن در SQL بهره ببرید.
چگونه این نوع داده را حذف کنم!؟
شما میتوانید به سادگی نوع دادهی ایجادشده توسط CLR را در مسیر زیر بیابید و اقدام به حذف آن نمایید:
همانطور که مشاهده میشود؛ حتی نوع دادهی سیستمی hierarchyid که جهت ساختار سلسلهمراتبی مانند چارت سازمانی یا درخت تجهیزات استفاده میشود؛ نیز یک نوع دادهی CLR است.
آیا راه دیگری نیز برای افزودن این نوع داده به SQL به جز Publish کردن وجود دارد؟
مانند بسیاری دیگر از گونههای پروژه، در اینجا نیز شما یک فایل DLL خواهید داشت. این فایل برپایهی تنظیماتی که شما در قسمت Properties پروژهی خود انجام میدهید ساخته میشود. پس از تغییر مسیر فایل DLL در دستور زیر توسط یک New Query از Database خود، آن را اجرا کنید:
CREATE ASSEMBLY JalaliDate FROM 'F:\prgJalaliDate.dll' WITH PERMISSION_SET = SAFE;
ALTER ASSEMBLY JalaliDate FROM 'F:\prgJalaliDate.dll'
select * from sys.assemblies select * from sys.assembly_files
CREATE TYPE dbo.JalaliDate EXTERNAL NAME JalaliDate.[JalaliDate];
همچنین چنانچه در SQL Server 2012 از منوی راستکلیک پایگاه دادهها روی گزینه Tasks و سپس Generate Scripts را انتخاب کنیم، از مشاهدهی سند ساخته شده، درخواهیم یافت که حتی دستورهای مربوط به ساخت اسمبلی CLR با تبدیل فایل به کد در Scripts وجود دارد و با اجرای آن در سروری دیگر، انتقال مییابد.
GO /****** Object: SqlAssembly [prgJalaliDate] Script Date: 2013/04/30 08:27:00 ب.ظ ******/ CREATE ASSEMBLY [prgJalaliDate] FROM 0x4D5A90000300000004000000FFFF0000B8000000000000 ..... بقیهی کدها حذف شده WITH PERMISSION_SET = SAFE GO ALTER ASSEMBLY [prgJalaliDate] ADD FILE FROM 0x4D6963726F736F667420432F432B2B204D534620372E30300D0A1A44530..... بقیهی کدها حذف شده AS N'prgJalaliDate.pdb' GO /****** Object: UserDefinedType [dbo].[JalaliDate] Script Date: 2013/04/30 08:27:00 ب.ظ ******/ CREATE TYPE [dbo].[JalaliDate] EXTERNAL NAME [prgJalaliDate].[JalaliDate] GO
دنباله دارد ...
سلام
اما من توی tfs هرکاری میکنم امکانش نیست فولدر packages چک این نشه.
یه فایل ساختم توی ریشه پروژه به نام tfignore. و تنظیمات بهش دادم اما اعمال نشد.
اما من توی tfs هرکاری میکنم امکانش نیست فولدر packages چک این نشه.
یه فایل ساختم توی ریشه پروژه به نام tfignore. و تنظیمات بهش دادم اما اعمال نشد.