مطالب
آموزش LINQ بخش سوم
در ادامه سری آموزشی LINQ  به بررسی متغیرهای Range می‌پردازیم:
4 عنصر یک عبارت پرس و جو عبارتند از:
• علملگرهای LINQ
• کلمات کلیدی Keyword
• متغیر‌های Range

Range Variable : متغیر تعریف شده‌ی در یک محدوده خاص.

  عبارت پرس و جوی زیر را در نظر بگیرد:
var query = from word in list
where word.StartsWith("a")
select word;
در این پرس و جو (from,in,where,select) کلمات کلیدی محسوب می‌شوند. البته where و select می‌توانند به عنوان عملگر محسوب شوند.
شناسه‌ی list یک متغیر محلی است و تنها موردی که باقی می‌ماند شناسه‌ی word است که به آن متغیر Range می‌گوییم. متغیر‌های Range همانند متغیر‌های مرسوم مورد استفاده‌ی در برنامه‌ها هستند که بصورت فقط خواندنی مهیا شده اند. با این اوصاف متغیر‌های Range در ابتدا کمی عجیب به نظر می‌رسند. به این علت که در وسط عبارت پرس و جو معرفی می‌شوند و نیازی به تعریف شدن به روش مرسوم به شکل زیر را ندارند:
 String word;
در این حالت معرفی Word از طریق عبارت from انجام می‌شود. کامپایلر نوع داده‌ی متغیر را از طریق فرآیندی به نام Type Inference مشخص می‌کند. در مثال بالا کامپایلر تشخیص می‌دهد که Word از نوع string  است؛ به این علت که جدا شده از <list<string  می‌باشد.

متغیر word  در دو حالت ممکن است قابل دسترس نباشد :
  • پایان پرس و جو
  • مواجه شدن با کلمه کلیدی into . این کلمه‌ی کلیدی برای اتصال دو Query استفاده می‌شود.

نکته
:در بعضی مواقع باید وضعیت متغیر Range را صریحا مشخص کنیم؛ بطور مثال کد زیر با خطا مواجه خواهد شد:
object[] ints = new object[] { 1, 2, 3 };
           var query = from num in ints
                        where num < 3
                        select num;
در زمان پردازش دستور Where، کامپایلر نمی‌تواند عملگر مقایسه‌ای را برای یک نوع int و یک نوع object اجرا کند. برای حل این مشکل بصورت صریح (Explicit) نوع متغیر Range را مشخص می‌کنیم:
var query = from int num in ints
where num < 3
select num;
همانطور که می‌بینید در این حالت به کامپایلر اعلام می‌کنیم که num از نوع int می‌باشد و cast کردن با موفقیت انجام می‌شود و خروجی همان چیزی است که ما انتظار داریم.

تذکر : بهتر است از تعریف صریح متغیر Range پرهیز کنیم؛ مگر در شرایطی مثل کد بالا .

قطعه کد زیر به‌راحتی کامپایل می‌شود و نیازی به اعلان صریح نوع متغیر range نیست. زیر از طریق مکانیزیم Type Inference نوع متغیر مشخص شده است.
List<string> list = new List<string> {"LINQ","Query","adventure"};
var query = from string word in list
where word.Contains("r")
orderby word ascending
select word;
اعلان صریح متغیر Range باعث می‌شود که پشت پرده، عملیات <Cast<T اتفاق بیافتد و در مواقع غیر ضروری مثل کد فوق ممکن است کارآیی را کاهش دهد. یکی از نقاطی که در صورت پایین بودن کارآیی دستورات LINQ باید بررسی شود همین مورد CAST است. البته تنها استثنایی که در این مورد وجود دارد، توالی‌های غیر جنریک هستند (non generic Enumerable). در این حالت باید از Cast استفاده کرد.
متغیر Range در محدوده‌ی مورد استفاده باید از یک شناسه‌ی یکتا برخوردار باشد.
 string word="test";
List<string> list = new List<string> {"LINQ","Query","adventure"};
var query = from string word in list
where word.Contains("r")
orderby word ascending
select word;
همانطور که مشاهده می‌کنید کامپایلر خطای تعریف دو شناسه‌ی یکتا را در یک محدوده، اعلام می‌کند.

تا اینجا از طریق کلمه‌ی کلیدی from، متغیری را تعریف کردیم. با استفاده از کلمات کلیدی let ،into و join  نیز می‌توان متغیر‌های Range تعریف کرد.

عبارت let

کلمه‌ی کلیدی let این امکان را فراهم می‌کند تا یک متغیر Range جدید را ایجاد کرده و در عبارت‌های بعدی از آن استفاده کنیم. در کد زیر از طریق کلمه‌ی کلیدی let، یک متغیر Range جدید را بنام IsDairy تعریف می‌کنیم که از نوع bool  می‌باشد:
 Ingredient[] ingredients =
{
   new Ingredient {Name = "Sugar", Calories = 500},
   new Ingredient {Name = "Egg", Calories = 100},
   new Ingredient {Name = "Milk", Calories = 150},
   new Ingredient {Name = "Flour", Calories = 50},
   new Ingredient {Name = "Butter", Calories = 200}
};

IEnumerable<Ingredient> highCalDairyQuery =
from i in ingredients
let isDairy = i.Name == "Milk" || i.Name == "Butter"
where i.Calories >= 150 && isDairy
select i;

foreach (var ingredient in highCalDairyQuery)
{
   Console.WriteLine(ingredient.Name);
}
  متغیر isDairy در عبارت (clause) بعدی که where باشد، مورد استفاده قرار گرفته است. توجه داشته باشید که متغیر i  تعریف شده‌ی در ابتدای پرس و جو، در بخش Select قابل دسترسی است. دستور let باعث از دسترس خارج شدن متغیر در بخش بعدی نمی‌شود.

در کد زیر قصد داریم عملیات‌های زیر را بر روی توالی ورودی اعمال کنیم:
1- جدا کردن عناصر توالی ورودی بر اساس جدا کننده‌ی "  ," 
2- تبدیل همه‌ی حروف عناصر توالی ایجاد شده به حروف بزرگ
3- جدا کردن عناصر توالی حاصل از مرحله‌ی 2، به شرط برابر بودن با MILK,BUTTER,CHEESE
4- نمایش توالی ایجاد شده
string[] csvRecipes = { "milk,sugar,eggs", "flour,BUTTER,eggs", "vanilla,ChEEsE,oats" };
var dairyQuery = from csvRecipe in csvRecipes
let ingredients = csvRecipe.Split(',')
from ingredient in ingredients
let uppercaseIngredient = ingredient.ToUpper()
where
  uppercaseIngredient == "MILK" ||
  uppercaseIngredient == "BUTTER" ||
  uppercaseIngredient == "CHEESE"
select uppercaseIngredient;

foreach (var dairyIngredient in dairyQuery)
{
   Console.WriteLine($"{dairyIngredient} is dairy");
}
همانطور که مشاهده می‌کنید متغیر ایجاد شده‌ی توسط let می‌تواند یک مقدار عددی (مثال قبل) و یا یک مجموعه را در خود ذخیره کند (مثال فوق).

 عبارت Into 
متغیر جدیدی که توسط این دستور ایجاد می‌شود، می‌تواند نتیجه‌ی حاصل از دستور Select را در خود ذخیره کند. در کد زیر یک نوع بی‌نام ایجاد کرده و در ادامه‌ی پرس و جو از آن استفاده می‌کنیم:
 Ingredient[] ingredients =
{
   new Ingredient {Name = "Sugar", Calories = 500},
   new Ingredient {Name = "Egg", Calories = 100},
   new Ingredient {Name = "Milk", Calories = 150},
   new Ingredient {Name = "Flour", Calories = 50},
   new Ingredient {Name = "Butter", Calories = 200}
};

IEnumerable<Ingredient> highCalDairyQuery =
from i in ingredients
select new //نوع بی نام
{
  OriginalIngredient = i,
  IsDairy = i.Name == "Milk" || i.Name == "Butter",
  IsHighCalorie = i.Calories >= 150
}
into temp
where temp.IsDairy && temp.IsHighCalorie
select temp.OriginalIngredient;

foreach (var ingredient in highCalDairyQuery)
{
   Console.WriteLine(ingredient.Name);
}
نکته‌ای که در ابتدای این بحث اشاره شد، در این مثال خود را نشان می‌دهد و آن هم عدم دسترسی به متغیر i در بخش پایانی پرس و جو (select  نهایی) می‌باشد.

در ادامه‌ی این سری آموزشی، به بررسی عبارت join  می‌پردازیم. 
مطالب
آشنایی با Oslo - قسمت اول

Oslo پلتفرم جدید مدل‌سازی مایکروسافت است که در سال‌های آتی مورد استفاده قرار خواهد گرفت و همچنین این روزها در مجامع توسعه و طراحی برنامه‌ها به شدت مورد بحث و توجه است. به همین جهت در طی مقالاتی با این پلتفرم جدید بیشتر آشنا خواهیم شد.

دریافت Oslo

Oslo از سه قسمت عمده تشکیل شده است:
  • الف) زبان مدل سازی M
  • ب) ابزار مدل سازی Quadrant
  • ج) استفاده از SQL Server به عنوان مخزن

زبان مدل سازی M از سه قسمت به نام‌های MGraph ، MGrammer و MSchema تشکیل می‌شود.
MGrammer : گرامر مورد استفاده در SDL را تعریف می‌کند. Syntax Directed Translation
MSchema : طرح مدل را تعریف خواهد کرد.
MGraph : اگر MSchema بیانگر انواع باشد، MGraph بیانگر وهله‌ها خواهد بود.

یک مثال:
برنامه‌ی Intellipad را اجرا کنید (فرض بر این است که SDK فوق را نصب کرده‌اید)



در اینجا حالت را بر روی M Mode قرار دهید (مطابق تصویر) و همچنین از منوی ظاهر شده‌ی M Mode ، گزینه‌ی Generic T-SQL preview را هم انتخاب کنید.

اولین ماژول ما به صورت زیر است:

module Test1
{
type ApplicationUser
{
UserID : Integer64=AutoNumber();
FirstName :Text#15;
LastName : Text#25;
Password : Text#10;
} where identity UserID;
}

ابتدا نام ماژول مشخص می‌شود. شبیه به معرفی یک فضای نام در برگیرنده‌ی اشیای مربوطه. سپس type ، بیانگر همان MSchema خواهد بود.
در این مثال شناسه‌ی کاربری از نوع Integer64 خود افزایش یابنده تعریف شده است (نوع identity در اس کیوال سرور).
فیلدهای نام ، نام خانوادگی و کلمه‌ی عبور از نوع متنی با اندازه‌های مشخص 15 ، 25 و 10 کاراکتر تعریف شده‌اند. اگر اندازه مشخص نبود نوع را تنها Text تعریف کنید.
نکته:
1-اگر پس از Text علامت ? قرار گیرد، به معنای فیلدی از نوع nullable خواهد بود و برعکس. زیبایی Intellipad هم در اینجا است که بلافاصله پس از تایپ شما، عبارت T-SQL معادل را تولید می‌کند.
2-در اینجا UserID‌ به صورت identity معرفی شده است. در زبان ام ، identity همانند primary key‌ در عبارات T-SQL عمل می‌کند و نباید اشتباه گرفته شود.

تا اینجا فقط یک type تعریف شده است. برای تبدیل آن به یک جدول باید آن‌را توسعه داد.

ApplicationUserCollection : ApplicationUser*;

این سطر را به پس از تعریف type اضافه نمائید. علامت ستاره در اینجا به معنای صفر یا بیشتر است و جهت بسط نوع تعریف شده به یک مجموعه به کار می‌رود. اکنون با اضافه شدن این سطر، Intellipad بلافاصله عبارات T-SQL معادل را تولید خواهد کرد که در تصویر مشخص است. به این صورت MGraph ما که بیانگر وهله‌هایی از نوع ApplicationUser هستند تولید گردید.

اکنون قصد داریم گروهی از کاربرها را به صورت نمونه ایجاد کنیم:

ApplicationUserCollection
{
//using a named instance
User1 {
FirstName="user1",
LastName="name1",
Password="1@34"
},
User2 {
FirstName="user2",
LastName="name2",
Password="123@4"
},
User3 {
FirstName="user3",
LastName="name3",
Password="56#2"
},
User4 {
FirstName="user4",
LastName="name4",
Password="789@5"
}
}

سطرهای فوق را پس از تعریف ApplicationUserCollection در Intellipad اضافه کنید. بلافاصله Intellipad عبارات T-SQL معادل را برای ما تولید خواهد کرد.



ادامه دارد ...

مطالب
بهبود عملکرد SQL Server Locks در سیستم‌های با تعداد تراکنش بالا در Entity Framework
بر اساس رفتار پیش فرض در دیتابیس SQL Server، در زمان انجام دادن یک دستور که منجر به ایجاد تغییرات در اطلاعات موجود در جدول می‌شود (برای مثال دستور Update)، جدول مربوطه به صورت کامل Lock می‌شود، ولو آن دستور Update، فقط با یکی از رکوردهای آن جدول کار داشته باشد.

در سیستم‌های با تعداد تراکنش بالا و دارای تعداد زیاد کلاینت، این رفتار پیش فرض موجب ایجاد صفی از تراکنش‌های در حال انتظار بر روی جداولی می‌شود که ویرایش‌های زیادی بر روی آنها رخ می‌دهد.
اگر چه که بنظر این مشکل راه حل‌های زیادی دارد، لکن آن راه حلی که همیشه موثر عمل می‌کند استفاده از SQL Server Table Hints است.
SQL Server Table Hints به تمامی آن دستوراتی گفته می‌شود که هنگام اجرای دستور اصلی (برای مثال Select و یا Update) رفتار پیش فرض SQL Server را بر اساس Hint ارائه شده تغییر می‌دهند.
لیست کامل این Hint‌ها را می‌توانید در اینجا مشاهده کنید.
Hint ای که در اینجا برای ما مفید است، آن است که به SQL Server بگوییم هنگام اجرای دستور Update، به جای Lock کردن کل جدول، فقط رکورد در حال ویرایش را Lock کند، و این باعث می‌شود تا باقی تراکنش ها، که ای بسا با سایر رکوردهای آن جدول کار داشته باشند متوقف نشوند، که البته این مسئله کمی به افزایش مصرف حافظه می‌انجامد، لکن مقدار افزایش بسیار ناچیز است.
این Hint که rowlock نام دارد در تراکنش‌های با Isolation Level تنظیم شده بر روی Snapshot باید با یک Table Hint دیگر با نام updlock ترکیب شود.
توضیحات مفصل‌تر این دو Hint در لینک مربوطه آمده است.
بنابر این، بجای دستور
update products
set Name = "Test"
Where Id = 1
داریم
update products with (nolock,updlock)
set Name = "Test"
where Id = 1
تا اینجا مشکل خاصی وجود ندارد، آنچه که از اینجا به بعد اهمیت دارد این است که در هنگام کار با Entity Framework، اساسا ما نویسنده دستورات Update نیستیم که به آنها Hint اضافه کنیم یا نه، بلکه دستورات SQL بوسیله Entity Framework ایجاد می‌شوند.
در Entity Framework، مکانیزمی تعبیه شده است با نام Db Command Interceptor که به شما اجازه می‌دهد دستورات SQL ساخته شده را Log کنید و یا قبل از اجرا تغییر دهید، که برای اضافه نمودن Table Hint‌ها ما از این روش استفاده می‌کنیم، برای انجام این کار داریم: (توضیحات در ادامه)
    public class UpdateRowLockHintDbCommandInterceptor : IDbCommandInterceptor
    {
        public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<Int32> interceptionContext)
        {
            if (command.CommandType != CommandType.Text) return; // (1)
            if (!(command is SqlCommand)) return; // (2)
            SqlCommand sqlCommand = (SqlCommand)command;
            String commandText = sqlCommand.CommandText;
            String updateCommandRegularExpression = "(update) ";
            Boolean isUpdateCommand = Regex.IsMatch(commandText, updateCommandRegularExpression, RegexOptions.IgnoreCase | RegexOptions.Multiline); // You may use better regular expression pattern here.
            if (isUpdateCommand)
            {
                Boolean isSnapshotIsolationTransaction = sqlCommand.Transaction != null && sqlCommand.Transaction.IsolationLevel == IsolationLevel.Snapshot;
                String tableHintToAdd = isSnapshotIsolationTransaction ? " with (rowlock , updlock) set " : " with (rowlock) set ";
                commandText = Regex.Replace(commandText, "^(set) ", (match) =>
                {
                    return tableHintToAdd;
                }, RegexOptions.IgnoreCase | RegexOptions.Multiline);
                command.CommandText = commandText;
            }
        }
این کد در قسمت (1) ابتدا تشخیص می‌دهد که آیا این یک Command دارای Command Text است یا خیر، برای مثال اگر فراخوانی یک Stored Procedure است، ما با آن کاری نداریم.
در قسمت دوم تشخیص می‌دهیم که آیا با SQL Server در حال تعامل هستیم، یا برای مثال با Oracle و ...، که ما برای Table Hint‌ها فقط با SQL Server کار داریم.
سپس باید تشخیص دهیم که آیا این یک دستور update است یا خیر ؟ برای این منظور از Regular Expression‌ها استفاده کرده ایم، که خیلی به بحث آموزش این پست مربوط نیست، به صورت کلی از Regular Expression‌ها برای یافتن و بررسی و جایگزینی عبارات با قاعده در هنگام کار با رشته‌ها استفاده می‌شود.
ممکن است Regular Expression ای که شما می‌نویسید بسیار بهتر از این نمونه باشد، که در این صورت خوشحال می‌شوم در قسمت نظرات آنرا قرار دهید.
در نهایت با بررسی Transaction Isolation Level مربوطه که Snapshot است یا خیر، به درج یک یا هر دو Table Hint مربوطه اقدام می‌نماییم.
اشتراک‌ها
ASP.NET 5 beta 6 منتشر شد

The new Microsoft.Framework.Caching.SqlServer package will allow you to use SQL Server as your cache store in ASP.NET 5 applications.

ASP.NET 5 beta 6 منتشر شد
اشتراک‌ها
مواردی که باید درباره Visual Studio Online account باید بدانید
With Visual Studio Online, I realized I have not installed an On-premise Team Foundation Server in a while.  The convenience of these online accounts always being available, having the server automatically upgraded, and of course access to services such as Cloud Load Test, Hosted Build and Application Insights takes it from an incredible inconvenience to a must have
مواردی که باید درباره Visual Studio Online account باید بدانید
نظرات مطالب
امکان تعریف اعضای static abstract در اینترفیس‌های C# 11
پشتیبانی از ریاضیات جنریک در C# 11

در C# 11، امکان انجام عملیات ریاضی بر روی نوع‌های جنریک میسر شده‌است که قسمتی از آن‌را در مطلب جاری مطالعه کردید. این ویژگی به همراه دو مزیت زیر است:
- اکنون اعضای استاتیک اینترفیس‌ها می‌توانند abstract هم باشند؛ یعنی کلاس‌های پیاده ساز آن‌ها باید این اعضای استاتیک را پیاده سازی کنند.
-  امکان تعریف عملگرهای استاتیک ریاضی در اینترفیس‌ها ممکن شده‌است:
 static T Add<T>(T left, T right) where T : INumber<T> => left + right;
در این مثال، نوع T، تنها می‌تواند از نوع <INumber<T باشد که یکی از اینترفیس‌های جدید NET 7. است. این اینترفیس نیز پیاده سازی کننده‌ی IAdditionOperators است که در آن امکان دسترسی به عملگر + وجود دارد. متد فوق را می‌توان تقریبا توسط تمام نوع‌های ریاضی توکار دات نت مورد استفاده قرار داد؛ از این جهت که تعاریف آن‌ها نیز در دات نت 7 برای پشتیبانی از INumber به‌روز رسانی شده‌اند.
یکی از مهم‌ترین مزیت‌های چنین امکانی، کاهش تعداد overload هایی است که باید توسعه دهندگان کتابخانه‌ها برای پشتیبانی از انواع و اقسام نوع‌های ریاضی ارائه دهند.
 

تغییرات API دات نت 7 در جهت پشتیبانی از ریاضیات جنریک

در مطلب جاری با اینترفیس جدید INumber آشنا شدیم که توسط آن مفاهیمی مانند صفر و یک و همچنین سربارگذاری عملگرهای ریاضی میسر شده‌است. تعداد این اینترفیس‌های توکار در دات نت 7، فراتر از یک مورد فوق است. برای مثال اینترفیس جدید IMinMaxValue امکان دسترسی به T.MinValue و T.MaxValue را میسر می‌کند.
یک مثال: امضای نوع Int32 در دات نت 7 به صورت زیر در آمده‌است:
public readonly struct Int32 : 
  IComparable, 
  IComparable<int>, 
  IConvertible, 
  IEquatable<int>, 
  IFormattable, 
  IParsable<int>, 
  ISpanFormattable, 
  ISpanParsable<int>, 
  IAdditionOperators<int, int, int>, 
  IAdditiveIdentity<int, int>, 
  IBinaryInteger<int>, 
  IBinaryNumber<int>, 
  IBitwiseOperators<int, int, int>, 
  IComparisonOperators<int, int, bool>, 
  IEqualityOperators<int, int, bool>, 
  IDecrementOperators<int>, 
  IDivisionOperators<int, int, int>, 
  IIncrementOperators<int>, 
  IModulusOperators<int, int, int>, 
  IMultiplicativeIdentity<int, int>, 
  IMultiplyOperators<int, int, int>, 
  INumber<int>, 
  INumberBase<int>, 
  ISubtractionOperators<int, int, int>, 
  IUnaryNegationOperators<int, int>, 
  IUnaryPlusOperators<int, int>, 
  IShiftOperators<int, int, int>, 
  IMinMaxValue<int>, 
  ISignedNumber<int>
یعنی تمام نوع‌های ریاضی توکار دات نت 7 از ریاضیات جنریک پشتیبانی می‌کنند. البته نوع‌ها زیر هنوز از یک چنین پشتیبانی برخوردار نیستند:
- System.Half
- System.Numerics.BigInteger
- System.Numerics.Complex
- System.Runtime.InteropServices.NFloat
- System.Int128
- System.UInt128

نوع‌های Int128 و UIn128 جزو تازه‌های دات نت 7 هستند (128-bit signed integer و 128-bit unsigned integer).

البته عموم ما از همان اینترفیس INumber و IBinaryInteger استفاده خواهیم کرد که خود آن نیز به صورت زیر تعریف شده‌است:
public interface INumber<TSelf> : 
IComparable, 
IComparable<TSelf>, 
IEquatable<TSelf>, 
IFormattable, 
IParsable<TSelf>, 
ISpanFormattable, 
ISpanParsable<TSelf>, 
IAdditionOperators<TSelf, TSelf, TSelf>, 
IAdditiveIdentity<TSelf, TSelf>, 
IComparisonOperators<TSelf, TSelf, bool>, 
IEqualityOperators<TSelf, TSelf, bool>, 
IDecrementOperators<TSelf>, 
IDivisionOperators<TSelf, TSelf, TSelf>, 
IIncrementOperators<TSelf>, 
IModulusOperators<TSelf, TSelf, TSelf>, 
IMultiplicativeIdentity<TSelf, TSelf>, 
IMultiplyOperators<TSelf, TSelf, TSelf>, 
INumberBase<TSelf>, 
ISubtractionOperators<TSelf, TSelf, TSelf>, 
IUnaryNegationOperators<TSelf, TSelf>, 
IUnaryPlusOperators<TSelf, TSelf> where TSelf : INumber<TSelf>?
نظرات مطالب
EF Code First #2
در SQL Server برای کار با بانک اطلاعاتی یک سری سطوح امنیتی وجود دارد. عنوان کردید که من یک نام کاربری دارم و پسود و از آن در رشته اتصالی استفاده می‌کنیم. بله. این درسته. اما این فقط ابتدای کار است. زمانیکه کاربری در SQL Server تعریف می‌شود یک سری سطح دسترسی را می‌شود به آن داد یا از آن گرفت. مثلا دسترسی اجرای SPها را نداشته باشد؛ دسترسی drop بانک اطلاعاتی را نداشته باشد؛ یا امکان فراخوانی delete را نداشته باشد. برای اینکه این موارد را بهتر مدیریت کنند یک schema تعریف می‌شود که در حقیقت قالبی است جهت مشخص سازی این سطوح دسترسی. dbo یکی از این قالب‌ها است که جزو مجموعه بالاترین سطوح دسترسی است. در هاست‌های اشتراکی که به مسایل امنیتی اهمیت می‌دهند امکان نداره به شما دسترسی dbo بدن. بله شما نام کاربری و کلمه عبور دارید اما schema سفارشی شما ممکن است دسترسی drop یا create بانک اطلاعاتی رو نداشته باشه (که در هاست‌های خوب ندارید).
این مساله چه مشکلی رو ایجاد می‌کنه؟
اگر کوئری پیش فرض شما select * from dbo.table1 باشد، در یک هاست اشتراکی با سطح دسترسی بالا که به شما دسترسی drop و create یک بانک اطلاعاتی رو نداده، دیگر اجرا نخواهد شد چون dbo نیستید. ضمنا روش صحیح و توصیه شده کار با SQL Server نیز ذکر schema در کوئری‌ها است زیرا سرعت اجرا را بالا می‌برد از این لحاظ که اگر آن‌را ذکر نکنید، SQL Server مجبور خواهد شد دست به سعی و خطا بزند. اما با ذکر آن یک راست از سطح دسترسی صحیح استفاده می‌شود. EF هم از همین روش استفاده می‌کنه. بنابراین لازم است schema رو اینجا در صورت مساوی نبودن با dbo حتما ذکر کرد و گرنه کوئری‌های شما دیگر اجرا نخواهند شد، چون دسترسی dbo رو ندارید.
نظرات مطالب
استفاده از توابع Scalar بجای case
در نسخه 2012 جهت سهولت در مهاجرت پایگاه داده‌های Access به SQL Server از توابع CHOOSE و IIF حمایت شده.
 
منتها تابع IIF چندان انعطاف پذیر نیست. مثلا اگر بخواهید به ازای چند حالت مشخص از داده‌های یک فیلد یک مقدار را برگردانید مجبورید چند تابع IIF تودرتو بنویسید. تودرتو بودن این تابع هم به 10 سطح محدود میشه.
اما CASE قابلیت‌ها و انعطاف پذیری بیشتری داره.
سوال میشه گاها کدام یک از این دو Performance یا کارایی بهتر دارد، در جواب میشه گفت هر دو برابر اند. در واقع IIF هنگام اجرا تبدیل به فرم CASE خواهد شد.
فرض کنید یک نظر سنجی تلوزیونی تنظیم کردیم که مردم از طریق پیامک نظر خودشان را به ما اعلام میکنند. شش گزینه هم داریم. برای انتخاب هر گزینه کافیست از اعداد 1 تا 6 استفاده کنیم. حال هنگام نمایش می‌خواهیم به جای اعداد مقدار متناظر ظاهر شود:

Use Tempdb
Go

CREATE TABLE [Sample] (value int);
INSERT INTO [Sample] VALUES (1),(2),(3),(4),(5),(6);
Go

--simple CASE Expression
SELECT value,
       CASE Value 
        WHEN 1 THEN 'Very Bad'
        WHEN 2 THEN 'Bad'
        WHEN 3 THEN 'Not Bad'
        WHEN 4 THEN 'Good'
        WHEN 5 THEN 'Very Good'
        WHEN 6 THEN 'Excellent'
       ELSE NULL
END AS [Result]
FROM [Sample];

--CHOOSE Scalar Function
SELECT value,
       CHOOSE(value,'Very Bad','Bad','Not Bad','Good','Very Good','Excellent')
FROM [Sample];


--nested IIF Scalr Function
SELECT value, 
IIF(value = 1, 'Very Bad',
  IIF(value = 2, 'Bad',
    IIF(value = 3, 'Not Bad',
      IIF(value = 4, 'Good',
        IIF(value = 5, 'Very Good', 'Excellent'
           )
         )
       )
     )
   )
FROM [Sample];
پاسخ به بازخورد‌های پروژه‌ها
تولید پویای رشته Sql و ارسال پارامتر برای عملگر Like
دقیقا مانند مباحث کار با پارامترها در ADO.NET است:
command.Parameters.AddWithValue("@p3", "%test%");
در اینجا هم در کوئری می‌نویسید like @p3 و مقدار آن‌را درصد دار تعریف می‌کنید:
                dataSource.GenericDataReader(
                    providerName: "System.Data.SQLite",
                    connectionString: "Data Source=" + System.IO.Path.Combine(AppPath.ApplicationPath, "data\\blogs.sqlite"),
                    sql: @"SELECT [url], [name], [NumberOfPosts], [AddDate]
                               FROM [tblBlogs]
                               WHERE [NumberOfPosts]>=@p1 or [name] like @p2",
                    parametersValues: new object[]
                    {
                        10 /* 1st parameter's value */, 
                        "%blog%" /* 2nd parameter's value */
                    }
                );