مثال 1: افزودن ردیفی به یک جدول بانک اطلاعاتی
امکان و ویژگی جدیدی به نام SPA قرار است به مجموعه اضافه شود. اطلاعات آن که شامل موارد ذیل است، نیاز است به جدول facilities اضافه شود:
facid: 9, Name: 'Spa', membercost: 20, guestcost: 30, initialoutlay: 100000, monthlymaintenance: 800.
insert into facilities (facid, name, membercost, guestcost, initialoutlay, monthlymaintenance) values (9, 'Spa', 20, 30, 100000, 800); -- OR insert into facilities values (9, 'Spa', 20, 30, 100000, 800);
context.Facilities.Add(new Facility { Name = "Spa", MemberCost = 20, GuestCost = 30, InitialOutlay = 100000, MonthlyMaintenance = 800 }); context.SaveChanges();
مثال 2: افزودن چندین ردیف از اطلاعات به یک جدول بانک اطلاعاتی
همان مثال قبلی را درنظر بگیرید. اینبار میخواهیم دو ردیف را به آن اضافه کنیم:
facid: 9, Name: 'Spa', membercost: 20, guestcost: 30, initialoutlay: 100000, monthlymaintenance: 800. facid: 10, Name: 'Squash Court 2', membercost: 3.5, guestcost: 17.5, initialoutlay: 5000, monthlymaintenance: 80.
insert into facilities (facid, name, membercost, guestcost, initialoutlay, monthlymaintenance) values (9, 'Spa', 20, 30, 100000, 800), (10, 'Squash Court 2', 3.5, 17.5, 5000, 80);
context.Facilities.Add(new Facility { Name = "Spa", MemberCost = 20, GuestCost = 30, InitialOutlay = 100000, MonthlyMaintenance = 800 }); context.Facilities.Add(new Facility { Name = "Squash Court 2", MemberCost = 3.5M, GuestCost = 17.5M, InitialOutlay = 5000, MonthlyMaintenance = 80 }); context.SaveChanges();
مثال 3: افزودن اطلاعات محاسبه شده به یک جدول بانک اطلاعاتی
اطلاعات زیر را درنظر بگیرید:
Name: 'Spa', membercost: 20, guestcost: 30, initialoutlay: 100000, monthlymaintenance: 800.
namespace EFCorePgExercises.Entities { public class FacilityConfiguration : IEntityTypeConfiguration<Facility> { public void Configure(EntityTypeBuilder<Facility> builder) { builder.HasKey(facility => facility.FacId); builder.Property(facility => facility.FacId).IsRequired().UseIdentityColumn(seed: 0, increment: 1);
CREATE TABLE [dbo].[Facilities]( [FacId] [int] IDENTITY(0,1) NOT NULL, --- ... CONSTRAINT [PK_Facilities] PRIMARY KEY CLUSTERED ( [FacId] ASC );
مثال 4: به روز رسانی اطلاعاتی از پیش موجود
میخواهیم مقدار InitialOutlay دومین زمین تنیس را از 8000 موجود به 10000 تغییر دهیم. با توجه به اینکه ID این زمین شماره 1 است، در حالت متداول SQL نویسی، به کدهای زیر خواهیم رسید:
update facilities set initialoutlay = 10000 where facid = 1;
var facility1 = context.Facilities.Find(1); facility1.InitialOutlay = 10000; context.SaveChanges();
EF-Core برای اینکه بتواند تغییرات اعمالی به یک شیء را محاسبه کند، نیاز دارد تا آن شیء را به نحوی در سیستم change tracking خودش موجود داشته باشد. هر نوع کوئری که در EF-Core نوشته میشود و به همراه متد AsNoTracking نیست، خروجی تک تک اشیاء حاصل از آن پیش از ارائهی نهایی، وارد سیستم change tracking آن میشوند. یعنی اگر مقادیر خواص این اشیاء را تغییر داده و بر روی آنها SaveChanges را فراخوانی کنیم، کوئریهای متناظر با به روز رسانی تنها این خواص تغییر یافته به صورت خودکار محاسبه شده و به بانک اطلاعاتی اعمال میشوند.
فراخوانی متد AsNoTracking بر روی کوئریهای EF-Core، تولید پروکسیهای change tracking را غیرفعال میکند. یک چنین کوئریهایی صرفا کاربردهای گزارشگیری فقط خواندنی را دارند و نسبت به کوئریهای معمولی، سریعتر و با مصرف حافظهی کمتری هستند. بنابراین نتایج حاصل از کوئریهای متداول EF-Core، به صورت پیشفرض (یعنی بدون داشتن متد AsNoTracking) هم خواندنی و هم نوشتنی با قابلیت اعمال به بانک اطلاعاتی هستند.
مثال 5: به روز رسانی چندین ردیف و چندین جدول در یک زمان
میخواهیم مقادیر MemberCost و GuestCost دو زمین تنیس را به 6 و 30 تغییر دهیم. روش انجام اینکار با SQL نویسی معمولی به صورت زیر است:
update cd.facilities set membercost = 6, guestcost = 30 where facid in (0,1);
int[] facIds = { 0, 1 }; var tennisCourts = context.Facilities.Where(x => facIds.Contains(x.FacId)).ToList(); foreach (var tennisCourt in tennisCourts) { tennisCourt.MemberCost = 6; tennisCourt.GuestCost = 30; } context.SaveChanges();
مثال 6: به روز رسانی اطلاعات یک ردیف بر اساس اطلاعات ردیفی دیگر
میخواهیم هزینهی دومین زمین تنیس را به نحوی ویرایش کنیم که 10 درصد بیشتر از هزینهی اولین زمین تنیس باشد.
روش پیشنهادی انجام اینکار با SQL نویسی مستقیم به صورت زیر است:
update cd.facilities facs set membercost = (select membercost * 1.1 from cd.facilities where facid = 0), guestcost = (select guestcost * 1.1 from cd.facilities where facid = 0) where facs.facid = 1;
var fac0 = context.Facilities.Where(x => x.FacId == 0).First(); var fac1 = context.Facilities.Where(x => x.FacId == 1).First(); fac1.MemberCost = fac0.MemberCost * 1.1M; fac1.GuestCost = fac0.GuestCost * 1.1M; context.SaveChanges();
میخواهیم تمام اطلاعات جدول bookings را حذف کنیم.
روش انجام اینکار با SQL نویسی مستقیم به صورت زیر است:
delete from bookings
context.Bookings.RemoveRange(context.Bookings.ToList()); context.SaveChanges();
البته هستند کتابخانههای ثالثی (^ و ^) که انجام به روز رسانی دستهای و یا حذف دستهای از رکوردها را تنها با یک کوئری SQL میسر میکنند؛ اما ... هنوز جزئی از EF استاندارد نشدهاند و مهمترین مشکل احتمالی این روشها، همگام نبودن context و سیستم change tacking، با نتیجهی حاصل از به روز رسانی یکبارهی صدها ردیف است.
مثال 8: حذف یک کاربر از جدول کاربران
میخواهیم کاربر شمارهی 37 را حذف کنیم.
روش انجام اینکار با SQL نویسی به صورت زیر است:
delete from members where memid = 37;
var mem37 = context.Members.Where(x => x.MemId == 37).First(); context.Members.Remove(mem37); context.SaveChanges();
یک نکته: امکان سادهتر حذف یک ردیف با داشتن ID آن
کوئری گرفتن از بانک اطلاعاتی، یک روش وارد کردن شیءای به context و سیستم change tacking آن است. در این حالت عموما فرض بر این است که ID شیء را نمیدانیم. اما اگر این ID مانند مثال جاری از پیش مشخص بود، نیازی نیست تا ابتدا از بانک اطلاعاتی کوئری گرفت و کل شیء را در حافظه وارد کرد. در این حالت خاص میتوان با استفاده از روش زیر، این ID را وارد سیستم tracking کرد و سپس حالت آنرا به Deleted تغییر داد و در آخر آنرا ذخیره کرد:
var entry = context.Entry(new Member { MemId = 37 }); entry.State = EntityState.Deleted; context.SaveChanges();
روش فوق چنین کوئریهایی را ایجاد میکند:
SET NOCOUNT ON; DELETE FROM [Members] WHERE [MemId] = @p0; SELECT @@ROWCOUNT;
مثال 9: حذف بر اساس یک sub-query
میخواهیم تمام کاربرانی را که هیچگاه رزروی را انجام ندادهاند، حذف کنیم.
این مورد نیز با SQL نویسی مستقیم نیز توسط یک کوئری دستهای قابل انجام است:
delete from members where memid not in (select memid from cd.bookings);
var mems = context.Members.Where(x => !context.Bookings.Select(x => x.MemId).Contains(x.MemId)).ToList(); context.Members.RemoveRange(mems); context.SaveChanges();
کدهای کامل این قسمت را در اینجا میتوانید مشاهده کنید.