مشخصات مقاله
-
668
-
0.0
-
2894
-
0
-
0
آموزش درج داده در Scenario disconnected در Entity Framework Core
آموزش درج داده در Scenario disconnected در Entity Framework Core
آموزش Insert داده در Scenario disconnected در Entity Framework Core
درمورد ذخیره Data در Data Base در سناریوی connected بحث کردیم
در این بخش به ذخیره ی Data در سناریوی disconnected می پردازیم.
ذخیره ی Data در سناریوی disconnected کمی متفاوت است. در این سناریو، DbContext اطلاعی از موجودیت های disconnected ندارد چرا که موجودیت ها خارج از scope نمونه ی فعلی DbContext اضافه شده اند یا تغییر کرده اند. پس باید موجودیت های disconnected را با EntityState مناسب به context اصطلاحا attatch کنیم که بتوانیم روی Data Base عملیات Create، Update و Delete انجام دهیم.
تصویر زیر عملیات CUD را در سناریوی disconnected نشان می دهد.
همان طور که در تصویر مشخص است، موجودیت های disconnected (موجودیت هایی که توسط DbContext دنبال نمی شوند) باید با EntityState مناسب به DbContext اصطلاحا attach شوند. برای مثال، Added state برای موجودیت های جدید، Modified state برای موجودیت هایی که ویرایش شده اند، و Deleted state برای موجودیت هایی که حذف شده اند پس از فراخوانی متد SaveChanges() موجب query های INSERT، UPDATE و DELETE در Data Base می شوند.
مراحل زیر باید برای درج، ویرایش و حذف رکورد توسط EF Core در Data Base انجام شود:
- Attach کردن موجودیت به DbContext با EntityState مناسب
- فراخوانی متد SaveChanges()
مثال زیر نحوه ی درج یک رکورد جدید به Data Base را با انجام مراحل بالا نشان می دهد:
//Disconnected entity
var std = new Student(){ Name = "Bill" };
using (var context = new SchoolContext())
{
//1. Attach an entity to context with Added EntityState
context.Add< Student >(std);
//or the followings are also valid
// context.Students.Add(std);
// context.Entry< Student >(std).State = EntityState.Added;
// context.Attach< Student >(std);
//2. Calling SaveChanges to insert a new record into Students table
context.SaveChanges();
}
در مثال بالا، Std یک disconnected instance از کلاس Student است. متد context.Add< Student >() یک موجودیت Student را با Added state به context اصطلاحا attach می کند. فراخوانی مت SaveChanges() دستور زیر را می سازد و در Data Base اجرا می کند:
exec sp_executesql N'SET NOCOUNT ON; INSERT INTO [Students] ([Name]) VALUES (@p0); SELECT [StudentId] FROM [Students] WHERE @@ROWCOUNT = 1 AND [StudentId] = scope_identity();',N'@p0 nvarchar(4000), @p1 nvarchar(4000) ',@p0=N'Bill' go
EF Core روش های مختلفی برای افزودن موجودیت های با Added state در اختیار می گذارد. در مثال بالا، همه دستورهای
context.Students.Add(std);
context.Entry< Student >(std).State = EntityState.Added;
context.Attach< Student >(std);
یک نتیجه دارند.
Entity Framework Core متدهای زیر را برای attach کردن موجودیت های disconnected با Added EntityState در اختیار می گذارد، که همه موجب اجرای دستور INSERT در Data Base می شوند.
توجه: متدهای DbContext بالا در EF Core معرفی شده اند ( در EF 6 و نسخه های قبل نیستند). هر دو نوع متدهای DbContext و DbSet کاری مشابه انجام می دهند.
درج Data ی رابطه ای (Relational Data)
در بخش قبل یاد گرفتیم چگونه روابط یک به یک، یک به چند و چند به چند بین موجودیت ها ایجاد کنیم. Entity Framework API همه ی Dataی رابطه موجود در entity های مرتبط درج می کند. از متدهای DbContext.Add یا DbSet.Add برای اضافه کردن موجودیت های مرتبط به Data Base استفاده کنید. متد Add موجودیت ها را به context اصطلاحا attach می کند و برای همه ی موجودیت های درون گراف موجودیت که Id شان خالی است یا null است یا مقدار پیش فرض دارد، AddedState می دهد. مثال زیر را در نظر بگیرید:
var stdAddress = new StudentAddress()
{
City = "SFO",
State = "CA",
Country = "USA"
};
var std = new Student()
{
Name = "Steve",
Address = stdAddress
};
using (var context = new SchoolContext())
{
// Attach an entity to DbContext with Added state
context.Add< Student >(std);
// Calling SaveChanges to insert a new record into Students table
context.SaveChanges();
}
در مثال بالا context.Add< Student >(std) یک شی از Student اضافه می کند. EF Core API از طریق navigation property درون Student به StudentAddress نیز دسترسی پیدا می کند و EntityState هردو را Added می کند. هنگام فراخوانی مت SaveChanges() دستور زیر در Data Base اجرا می شود:
exec sp_executesql N'SET NOCOUNT ON; INSERT INTO [Students] ([Name]) VALUES (@p0); SELECT [StudentId] FROM [Students] WHERE @@ROWCOUNT = 1 AND [StudentId] = scope_identity();',N'@p0 nvarchar(4000), @p1 nvarchar(4000) ',@p0=N'Steve' go exec sp_executesql N'SET NOCOUNT ON; INSERT INTO [StudentAddresses] ([Address], [City], [Country], [State], [StudentId]) VALUES (@p5, @p6, @p7, @p8, @p9); SELECT [StudentAddressId] FROM [StudentAddresses] WHERE @@ROWCOUNT = 1 AND [StudentAddressId] = scope_identity(); ',N'@p5 nvarchar(4000),@p6 nvarchar(4000),@p7 nvarchar(4000),@p8 nvarchar(4000), @p9 int',@p5=NULL,@p6=N'SFO',@p7=N'USA',@p8=N'CA',@p9=1 Go
درج چند رکورد
با استفاده از متدهای DbContext.AddRange و DbSet.AddRange چند موجودیت را در یک ارتباط با Data Base درج کنید. در این صورت لازم نیست متد DbContext.Add را چند بار فراخوانی کنید.
void AddRange(IEnumerable< Object > entities)void AddRange(param object[] entities)void AddRangeAsync(IEnumerable< Object >, CancellationToken)مثال زیر اضافه کردن لیستی از موجودیت های از نوع Student را با استفاده از متد AddRange نشان می دهد:
var studentList = new List< Student >() {
new Student(){ Name = "Bill" },
new Student(){ Name = "Steve" }
};
using (var context = new SchoolContext())
{
context.AddRange(studentList);
context.SaveChanges();
}
مثال بالا دو رکورد جدید به جدول Students اضافه می کند.
می توان لیستی از انواع مختلف موجودیت را نیز به این شیوه درج کرد:
var std1 = new Student(){ Name = "Bill" };
var std2 = new Student(){ Name = "Steve" };
var computer = new Course() { CourseName = "Computer Science" };
var entityList = new List< Object >() {
std1,
std2,
computer
};
using (var context = new SchoolContext())
{
context.AddRange(entityList);
// or
// context.AddRange(std1, std2, computer);
context.SaveChanges();
}
در مثال بالا، entityList از نوع List< Object > است و می تواند حاوی هرنوع entity باشد. متد AddRange() همه ی موجودیت های درون آن را به context اضافه می کند و متد SaveChanges() برای همشان دستور INSERT می سازد و در Data Base اجرا می کند. (در یک ارتباط به Data Base).
EF Core عملکرد کار با Data Base را با اجرای دستور INSERT برای همه ی موجودیت های بالا در یک database round trip، بهبود بخشیده است. مثال بالا بصورت زیر در Data Base اجرا می شود:
exec sp_executesql N'SET NOCOUNT ON; INSERT INTO [Courses] ([CourseName], [Description]) VALUES (@p0, @p1); SELECT [CourseId] FROM [Courses] WHERE @@ROWCOUNT = 1 AND [CourseId] = scope_identity(); DECLARE @inserted1 TABLE ([StudentId] int, [_Position] [int]); MERGE [Students] USING ( VALUES (@p2, 0), (@p3, 1)) AS i ([Name], _Position) ON 1=0 WHEN NOT MATCHED THEN INSERT ([Name]) VALUES (i.[Name]) OUTPUT INSERTED.[StudentId], i._Position INTO @inserted1; SELECT [t].[StudentId] FROM [Students] t INNER JOIN @inserted1 i ON ([t].[StudentId] = [i].[StudentId]) ORDER BY [i].[_Position]; ',N'@p0 nvarchar(4000),@p1 nvarchar(4000),@p2 nvarchar(4000),@p3 nvarchar(4000)', @p0=N'Computer Science',@p1=NULL,@p2=N'Steve',@p3=N'Bill' go
درج Data با استفاده از DbSet
همان طور که قبلا هم اشاره شد، می توانید از DbSet برای ذخیره موجودیت ها استفاده کنید، به شیوه ای که در EF 6.x انجام می شود.
از متدDbSet< TEntity>.Add() برای attach کردن موجودیت با Added state یا از متد DbSet برای attach دسته ای از موجودیت ها با Added state استفاده کنید:
var std = new Student()
{
Name = "Bill"
};
using (var context = new SchoolContext())
{
context.Students.Add(std);
// or
// context.Students.Attach(std);
context.SaveChanges();
}در مثال بالا، نوع context.Students DbSet< Student > است. پس فقط می توان موجودیت های از نوع Student را اضافه کرد.
context.Students.Add(std)موجودیت Student را با Added state به Context اصطلاحا attach می کند و پس از فراخوانی متدSaveChanges()دستور INSERT ساخته و اجرا می شود.
در بخش بعد به نحوه ی update موجودیت های disconnected می پردازیم.