هدف از این سری مثالها، آشنایی با متدها و توابعی است که در حین کار با خواص رشتهای در LINQ to Entities، مجاز به استفادهی از آنها هستیم و همچنین اگر تابعی در EF-Core هنوز تعریف نشده بود، راه حل چیست.
مثال 1: نام تمام کاربران را با قالب 'Surname, Firstname' نمایش دهید.
متد Select میتواند به همراه اعمال محاسباتی سادهای نیز باشد که نمونهای از آنرا در اینجا مشاهده میکنید.
با این خروجی:
مثال 2: تمام امکاناتی را که با Tennis شروع میشوند، لیست کنید.
این گزارش به همراه تمام ستونهای جدول است.
متدهای استانداردی مانند StartsWith، EndsWith و Contains را میتوان بر روی خواص رشتهای بکار برد.
با این خروجی:
مثال 3: تمام امکاناتی را که با tennis شروع میشوند، لیست کنید. این جستجو باید غیرحساس به بزرگی و کوچکی حروف باشد.
این گزارش به همراه تمام ستونهای جدول است.
نیازی به انجام مجزای این تمرین نیست؛ چون پاسخ آن همان پاسخ مثال 2 است. Collation پیشفرض در SQL Server، غیرحساس به بزرگی و کوچکی حروف است. بنابراین چه tennis را جستجو کنیم و یا TeNnis را، تفاوتی نمیکند.
مثال 4: شماره تلفنهای دارای پرانتز را لیست کنید.
این گزارش باید به همراه ستونهای memid, telephone باشد.
روش اول: در اینجا دوبار از متد Contains استفاده شدهاست:
با این خروجی:
روش دوم: اگر میخواهیم کنترل بیشتری را بر روی خروجی نهایی LIKE تولیدی داشته باشیم، میتوان از متد سفارشی استاندارد EF.Functions.Like استفاده کرد که از حروف wild cards نیز پشتیبانی میکند:
با این خروجی:
مثال 5: کد پستیها 5 رقمی هستند. گزارشی را تهیه کنید که در آن اگر کدپستی کمتر از 5 رقم بود، ابتدای آن با صفر شروع شود.
هدف اصلی از این مثال، اعمال متد PadLeft(5, '0') به خاصیت member.ZipCode است.
روش اول: EF-Core فعلا قابلیت ترجمهی PadLeft(5, '0') را به معادل SQL آنرا ندارد. به همین جهت مجبور هستیم ابتدا ZipCodeها را به صورت رشتهای بازگشت دهیم که در اینجا استفادهی از Convert.ToString مجاز است.
با این خروجی:
سپس میتوان بر روی لیست آمادهی موجود در حافظه، از LINQ to Objects استفاده کرد و در این حالت دسترسی کاملی به تمام امکانات زبان #C وجود دارد:
روش دوم: SQL Server به همراه تابع استانداردی به نام Replicate است که از آن میتوان برای شبیه سازی PadLeft، بدون متوسل شدن به LINQ to Objects، استفاده کرد. اما چون این تابع هنوز به EF-Core معرفی نشدهاست، نیاز است خودمان اینکار را انجام دهیم. در این روش، از متد SqlDbFunctionsExtensions.SqlReplicate استفاده میشود. روش تعریف این نوع متدها را در مطلب «امکان تعریف توابع خاص بانکهای اطلاعاتی در EF Core» پیشتر بررسی کردهایم که برای مثال در اینجا چنین شکلی را پیدا میکند:
پس از آن فقط کافی است متد AddCustomSqlFunctions را به Context برنامه معرفی کنیم:
اکنون میتوان از تابع SqlDbFunctionsExtensions.SqlReplicate جهت شبیه سازی PadLeft به صورت زیر استفاده کرد:
با این خروجی:
مثال 6: اولین حرف نام خانوادگی کاربران در کل ردیفهای جدول چندبار تکرار شدهاست؟
این گزارش باید به همراه ستونهای letter, count باشد.
هدف از این مثال بیان مجاز بودن استفادهی از متد Substring بر روی خواص رشتهای است که EF-Core امکان ترجمهی آنها را به کدهای SQL دارد.
با این خروجی:
مثال 7: حروف '-','(',')', ' ' را از شماره تلفنها حذف کنید.
این گزارش باید به همراه ستونهای memid, telephone باشد.
بانک اطلاعاتی PostgreSQL به همراه تابع استاندارد regexp_replace است و میتوان از آن برای حل یک چنین مسایلی استفاده کرد:
اما SQL Server هنوز هم به همراه یک چنین تابعی نیست. بنابراین از روش زیر نیز میتوان مثال جاری را حل کرد:
با این خروجی:
کدهای کامل این قسمت را در اینجا میتوانید مشاهده کنید.
مثال 1: نام تمام کاربران را با قالب 'Surname, Firstname' نمایش دهید.
var members = context.Members .Select(member => new { Name = member.Surname + ", " + member.FirstName }) .ToList();
با این خروجی:
مثال 2: تمام امکاناتی را که با Tennis شروع میشوند، لیست کنید.
این گزارش به همراه تمام ستونهای جدول است.
var facilities = context.Facilities .Where(facility => facility.Name.StartsWith("Tennis")) .ToList();
با این خروجی:
مثال 3: تمام امکاناتی را که با tennis شروع میشوند، لیست کنید. این جستجو باید غیرحساس به بزرگی و کوچکی حروف باشد.
این گزارش به همراه تمام ستونهای جدول است.
نیازی به انجام مجزای این تمرین نیست؛ چون پاسخ آن همان پاسخ مثال 2 است. Collation پیشفرض در SQL Server، غیرحساس به بزرگی و کوچکی حروف است. بنابراین چه tennis را جستجو کنیم و یا TeNnis را، تفاوتی نمیکند.
مثال 4: شماره تلفنهای دارای پرانتز را لیست کنید.
این گزارش باید به همراه ستونهای memid, telephone باشد.
روش اول: در اینجا دوبار از متد Contains استفاده شدهاست:
var members = context.Members .Select(member => new { member.MemId, member.Telephone }) .Where(member => member.Telephone.Contains("(") && member.Telephone.Contains(")")) .ToList();
روش دوم: اگر میخواهیم کنترل بیشتری را بر روی خروجی نهایی LIKE تولیدی داشته باشیم، میتوان از متد سفارشی استاندارد EF.Functions.Like استفاده کرد که از حروف wild cards نیز پشتیبانی میکند:
members = context.Members .Select(member => new { member.MemId, member.Telephone }) .Where(member => EF.Functions.Like(member.Telephone, "%[()]%")) .ToList();
مثال 5: کد پستیها 5 رقمی هستند. گزارشی را تهیه کنید که در آن اگر کدپستی کمتر از 5 رقم بود، ابتدای آن با صفر شروع شود.
هدف اصلی از این مثال، اعمال متد PadLeft(5, '0') به خاصیت member.ZipCode است.
روش اول: EF-Core فعلا قابلیت ترجمهی PadLeft(5, '0') را به معادل SQL آنرا ندارد. به همین جهت مجبور هستیم ابتدا ZipCodeها را به صورت رشتهای بازگشت دهیم که در اینجا استفادهی از Convert.ToString مجاز است.
با این خروجی:
SELECT CONVERT (NVARCHAR (MAX), [m].[ZipCode]) AS [Zip] FROM [Members] AS [m] ORDER BY CONVERT (NVARCHAR (MAX), [m].[ZipCode]);
var members = context.Members .Select(member => new { ZipCode = Convert.ToString(member.ZipCode) }) .OrderBy(m => m.ZipCode) .ToList(); // Now using LINQ to Objects members = members.Select(member => new { ZipCode = member.ZipCode.PadLeft(5, '0') }) .OrderBy(m => m.ZipCode) .ToList();
روش دوم: SQL Server به همراه تابع استانداردی به نام Replicate است که از آن میتوان برای شبیه سازی PadLeft، بدون متوسل شدن به LINQ to Objects، استفاده کرد. اما چون این تابع هنوز به EF-Core معرفی نشدهاست، نیاز است خودمان اینکار را انجام دهیم. در این روش، از متد SqlDbFunctionsExtensions.SqlReplicate استفاده میشود. روش تعریف این نوع متدها را در مطلب «امکان تعریف توابع خاص بانکهای اطلاعاتی در EF Core» پیشتر بررسی کردهایم که برای مثال در اینجا چنین شکلی را پیدا میکند:
namespace EFCorePgExercises.Utils { public static class SqlDbFunctionsExtensions { public static string SqlReplicate(string expression, int count) => throw new InvalidOperationException($"{nameof(SqlReplicate)} method cannot be called from the client side."); private static readonly MethodInfo _sqlReplicateMethodInfo = typeof(SqlDbFunctionsExtensions) .GetRuntimeMethod( nameof(SqlDbFunctionsExtensions.SqlReplicate), new[] { typeof(string), typeof(int) } ); public static void AddCustomSqlFunctions(this ModelBuilder modelBuilder) { modelBuilder.HasDbFunction(_sqlReplicateMethodInfo) .HasTranslation(args => { return SqlFunctionExpression.Create("REPLICATE", args, _sqlReplicateMethodInfo.ReturnType, typeMapping: null); }); } } }
namespace EFCorePgExercises.DataLayer { public class ApplicationDbContext : DbContext { // ... protected override void OnModelCreating(ModelBuilder modelBuilder) { // ... modelBuilder.AddCustomSqlFunctions(); // ... } } }
var newMembers = context.Members .Select(member => new { ZipCode = SqlDbFunctionsExtensions.SqlReplicate( "0", 5 - Convert.ToString(member.ZipCode).Length) + member.ZipCode }) .OrderBy(m => m.ZipCode) .ToList();
مثال 6: اولین حرف نام خانوادگی کاربران در کل ردیفهای جدول چندبار تکرار شدهاست؟
این گزارش باید به همراه ستونهای letter, count باشد.
var members = context.Members .Select(member => new { Letter = member.Surname.Substring(0, 1) }) .GroupBy(m => m.Letter) .Select(g => new { Letter = g.Key, Count = g.Count() }) .OrderBy(r => r.Letter) .ToList();
با این خروجی:
مثال 7: حروف '-','(',')', ' ' را از شماره تلفنها حذف کنید.
این گزارش باید به همراه ستونهای memid, telephone باشد.
بانک اطلاعاتی PostgreSQL به همراه تابع استاندارد regexp_replace است و میتوان از آن برای حل یک چنین مسایلی استفاده کرد:
select memid, regexp_replace(telephone, '[^0-9]', '', 'g') as telephone from members order by memid;
var members = context.Members .Select(member => new { member.MemId, Telephone = member.Telephone.Replace("-", "") .Replace("(", "") .Replace(")", "") .Replace(" ", "") }) .OrderBy(r => r.MemId) .ToList();
کدهای کامل این قسمت را در اینجا میتوانید مشاهده کنید.