Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Catatan
Hanya EF6 dan seterusnya - Fitur, API, dll. yang dibahas di halaman ini dimasukkan dalam Entity Framework 6. Jika Anda menggunakan versi yang lebih lama, beberapa atau semua informasi tidak berlaku.
Secara default, Code First akan mengonfigurasi semua entitas untuk melakukan perintah sisipkan, perbarui, dan hapus menggunakan akses tabel langsung. Mulai dari EF6 Anda dapat mengonfigurasi model Code First untuk menggunakan prosedur tersimpan untuk beberapa atau semua entitas dalam model Anda.
Pemetaan Entitas Dasar
Anda dapat memilih menggunakan prosedur tersimpan untuk menyisipkan, memperbarui, dan menghapus menggunakan FLUENT API.
modelBuilder
.Entity<Blog>()
.MapToStoredProcedures();
Melakukan ini akan menyebabkan Code First menggunakan beberapa konvensi untuk membangun bentuk prosedur tersimpan yang diharapkan dalam database.
- Tiga prosedur tersimpan bernama <type_name>_Insert,< type_name>_Update dan <type_name>_Delete (misalnya, Blog_Insert, Blog_Update, dan Blog_Delete).
- Nama parameter sesuai dengan nama properti.
Catatan
Jika Anda menggunakan HasColumnName() atau atribut Kolom untuk mengganti nama kolom untuk properti tertentu, maka nama ini digunakan untuk parameter alih-alih nama properti.
- Prosedur sisipkan tersimpan akan memiliki parameter untuk setiap properti, kecuali yang ditandai sebagai disimpan yang dihasilkan (identitas atau komputasi). Prosedur tersimpan harus mengembalikan tataan hasil dengan kolom untuk setiap properti yang dihasilkan penyimpanan.
- Prosedur tersimpan pembaruan akan memiliki parameter untuk setiap properti, kecuali untuk yang ditandai dengan pola penyimpanan yang dihasilkan dari 'Komputasi'. Beberapa token konkurensi memerlukan parameter untuk nilai aslinya, lihat bagian Token Konkurensi di bawah ini untuk detailnya. Prosedur tersimpan harus mengembalikan tataan hasil dengan kolom untuk setiap properti komputasi.
- Prosedur tersimpan penghapusan harus memiliki parameter untuk nilai kunci entitas (atau beberapa parameter jika entitas memiliki kunci komposit). Selain itu, prosedur penghapusan juga harus memiliki parameter untuk setiap kunci asing asosiasi independen pada tabel target (hubungan yang tidak memiliki properti kunci asing yang sesuai yang dinyatakan dalam entitas). Beberapa token konkurensi memerlukan parameter untuk nilai aslinya, lihat bagian Token Konkurensi di bawah ini untuk detailnya.
Menggunakan kelas berikut sebagai contoh:
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
}
Prosedur tersimpan default adalah:
CREATE PROCEDURE [dbo].[Blog_Insert]
@Name nvarchar(max),
@Url nvarchar(max)
AS
BEGIN
INSERT INTO [dbo].[Blogs] ([Name], [Url])
VALUES (@Name, @Url)
SELECT SCOPE_IDENTITY() AS BlogId
END
CREATE PROCEDURE [dbo].[Blog_Update]
@BlogId int,
@Name nvarchar(max),
@Url nvarchar(max)
AS
UPDATE [dbo].[Blogs]
SET [Name] = @Name, [Url] = @Url
WHERE BlogId = @BlogId;
CREATE PROCEDURE [dbo].[Blog_Delete]
@BlogId int
AS
DELETE FROM [dbo].[Blogs]
WHERE BlogId = @BlogId
Mengesampingkan Default
Anda dapat mengambil alih sebagian atau semua yang dikonfigurasi secara default.
Anda dapat mengubah nama satu atau beberapa prosedur tersimpan. Contoh ini mengganti nama prosedur tersimpan pembaruan saja.
modelBuilder
.Entity<Blog>()
.MapToStoredProcedures(s =>
s.Update(u => u.HasName("modify_blog")));
Contoh ini mengganti nama ketiga prosedur tersimpan.
modelBuilder
.Entity<Blog>()
.MapToStoredProcedures(s =>
s.Update(u => u.HasName("modify_blog"))
.Delete(d => d.HasName("delete_blog"))
.Insert(i => i.HasName("insert_blog")));
Dalam contoh ini, panggilan dirangkai bersama-sama, tetapi Anda juga dapat menggunakan sintaks blok lambda.
modelBuilder
.Entity<Blog>()
.MapToStoredProcedures(s =>
{
s.Update(u => u.HasName("modify_blog"));
s.Delete(d => d.HasName("delete_blog"));
s.Insert(i => i.HasName("insert_blog"));
});
Contoh ini mengganti nama parameter untuk properti BlogId pada prosedur tersimpan pembaruan.
modelBuilder
.Entity<Blog>()
.MapToStoredProcedures(s =>
s.Update(u => u.Parameter(b => b.BlogId, "blog_id")));
Panggilan ini semuanya dapat dirantai dan dapat dikomposisikan. Berikut adalah contoh yang mengganti nama ketiga prosedur tersimpan dan parameternya.
modelBuilder
.Entity<Blog>()
.MapToStoredProcedures(s =>
s.Update(u => u.HasName("modify_blog")
.Parameter(b => b.BlogId, "blog_id")
.Parameter(b => b.Name, "blog_name")
.Parameter(b => b.Url, "blog_url"))
.Delete(d => d.HasName("delete_blog")
.Parameter(b => b.BlogId, "blog_id"))
.Insert(i => i.HasName("insert_blog")
.Parameter(b => b.Name, "blog_name")
.Parameter(b => b.Url, "blog_url")));
Anda juga dapat mengubah nama kolom dalam kumpulan hasil yang berisi nilai yang dihasilkan database.
modelBuilder
.Entity<Blog>()
.MapToStoredProcedures(s =>
s.Insert(i => i.Result(b => b.BlogId, "generated_blog_identity")));
CREATE PROCEDURE [dbo].[Blog_Insert]
@Name nvarchar(max),
@Url nvarchar(max)
AS
BEGIN
INSERT INTO [dbo].[Blogs] ([Name], [Url])
VALUES (@Name, @Url)
SELECT SCOPE_IDENTITY() AS generated_blog_id
END
Hubungan Tanpa Kunci Asing di Kelas (Asosiasi Independen)
Ketika properti kunci asing disertakan dalam definisi kelas, parameter yang sesuai dapat diganti namanya dengan cara yang sama seperti properti lainnya. Ketika hubungan ada tanpa properti kunci asing di kelas , nama parameter default adalah <navigation_property_name>_<primary_key_name>.
Misalnya, definisi kelas berikut akan mengakibatkan parameter Blog_BlogId diharapkan dalam prosedur tersimpan untuk menyisipkan dan memperbarui Postingan.
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public Blog Blog { get; set; }
}
Mengesampingkan Default
Anda dapat mengubah parameter untuk kunci asing yang tidak disertakan dalam kelas dengan menyediakan jalur ke properti kunci utama ke metode Parameter.
modelBuilder
.Entity<Post>()
.MapToStoredProcedures(s =>
s.Insert(i => i.Parameter(p => p.Blog.BlogId, "blog_id")));
Jika Anda tidak memiliki properti navigasi pada entitas dependen (yaitu tidak ada properti Post.Blog) maka Anda dapat menggunakan metode Asosiasi untuk mengidentifikasi akhir hubungan lainnya lalu mengonfigurasi parameter yang sesuai dengan setiap properti kunci.
modelBuilder
.Entity<Post>()
.MapToStoredProcedures(s =>
s.Insert(i => i.Navigation<Blog>(
b => b.Posts,
c => c.Parameter(b => b.BlogId, "blog_id"))));
Token Konkurensi
Memperbarui dan menghapus prosedur tersimpan mungkin juga perlu menangani konkurensi:
- Jika entitas berisi token konkurensi, prosedur tersimpan dapat secara opsional memiliki parameter output yang mengembalikan jumlah baris yang diperbarui/dihapus (baris terpengaruh). Parameter semacam itu harus dikonfigurasi menggunakan metode RowsAffectedParameter.
Secara default EF menggunakan nilai pengembalian dari ExecuteNonQuery untuk menentukan berapa banyak baris yang terpengaruh. Menentukan parameter output yang terpengaruh baris berguna jika Anda melakukan logika apa pun dalam sproc Anda yang akan mengakibatkan nilai pengembalian ExecuteNonQuery salah (dari perspektif EF) di akhir eksekusi. - Untuk setiap token konkurensi akan ada parameter bernama <property_name>_Original (misalnya, Timestamp_Original ). Ini akan diteruskan nilai asli properti ini - nilai ketika dikueri dari database.
- Token konkurensi yang dihitung oleh database – seperti tanda waktu – hanya akan memiliki parameter nilai asli.
- Properti non-komputasi yang ditetapkan sebagai token konkurensi juga akan memiliki parameter untuk nilai baru dalam prosedur pembaruan. Ini menggunakan konvensi penamaan yang sudah dibahas untuk nilai baru. Contoh token seperti itu akan menggunakan URL Blog sebagai token konkurensi, nilai baru diperlukan karena ini dapat diperbarui ke nilai baru oleh kode Anda (tidak seperti token Tanda Waktu yang hanya diperbarui oleh database).
Ini adalah contoh kelas dan memperbarui prosedur tersimpan dengan token konkurensi tanda waktu.
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
[Timestamp]
public byte[] Timestamp { get; set; }
}
CREATE PROCEDURE [dbo].[Blog_Update]
@BlogId int,
@Name nvarchar(max),
@Url nvarchar(max),
@Timestamp_Original rowversion
AS
UPDATE [dbo].[Blogs]
SET [Name] = @Name, [Url] = @Url
WHERE BlogId = @BlogId AND [Timestamp] = @Timestamp_Original
Berikut adalah contoh kelas dan memperbarui prosedur tersimpan dengan token konkurensi non-komputasi.
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
[ConcurrencyCheck]
public string Url { get; set; }
}
CREATE PROCEDURE [dbo].[Blog_Update]
@BlogId int,
@Name nvarchar(max),
@Url nvarchar(max),
@Url_Original nvarchar(max),
AS
UPDATE [dbo].[Blogs]
SET [Name] = @Name, [Url] = @Url
WHERE BlogId = @BlogId AND [Url] = @Url_Original
Mengesampingkan Default
Anda dapat secara opsional memperkenalkan parameter yang terpengaruh baris.
modelBuilder
.Entity<Blog>()
.MapToStoredProcedures(s =>
s.Update(u => u.RowsAffectedParameter("rows_affected")));
Untuk token konkurensi komputasi database - di mana hanya nilai asli yang diteruskan - Anda hanya dapat menggunakan mekanisme penggantian nama parameter standar untuk mengganti nama parameter untuk nilai asli.
modelBuilder
.Entity<Blog>()
.MapToStoredProcedures(s =>
s.Update(u => u.Parameter(b => b.Timestamp, "blog_timestamp")));
Untuk token konkurensi non-komputasi – di mana nilai asli dan baru diteruskan – Anda dapat menggunakan kelebihan beban Parameter yang memungkinkan Anda memberikan nama untuk setiap parameter.
modelBuilder
.Entity<Blog>()
.MapToStoredProcedures(s => s.Update(u => u.Parameter(b => b.Url, "blog_url", "blog_original_url")));
Banyak ke Banyak Hubungan
Kita akan menggunakan kelas berikut sebagai contoh di bagian ini.
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public List<Tag> Tags { get; set; }
}
public class Tag
{
public int TagId { get; set; }
public string TagName { get; set; }
public List<Post> Posts { get; set; }
}
Banyak ke banyak hubungan dapat dipetakan ke prosedur tersimpan dengan sintaks berikut.
modelBuilder
.Entity<Post>()
.HasMany(p => p.Tags)
.WithMany(t => t.Posts)
.MapToStoredProcedures();
Jika tidak ada konfigurasi lain yang disediakan, bentuk prosedur tersimpan berikut digunakan secara default.
- Dua prosedur tersimpan bernama <type_two type_one>><_Insert dan< type_two> type_one><_Delete (misalnya, PostTag_Insert dan PostTag_Delete).
- Parameter akan menjadi nilai kunci untuk setiap jenis. Nama setiap parameter yang type_name<>_<property_name> (misalnya, Post_PostId dan Tag_TagId).
Berikut adalah contoh menyisipkan dan memperbarui prosedur tersimpan.
CREATE PROCEDURE [dbo].[PostTag_Insert]
@Post_PostId int,
@Tag_TagId int
AS
INSERT INTO [dbo].[Post_Tags] (Post_PostId, Tag_TagId)
VALUES (@Post_PostId, @Tag_TagId)
CREATE PROCEDURE [dbo].[PostTag_Delete]
@Post_PostId int,
@Tag_TagId int
AS
DELETE FROM [dbo].[Post_Tags]
WHERE Post_PostId = @Post_PostId AND Tag_TagId = @Tag_TagId
Mengesampingkan Default
Prosedur dan nama parameter dapat dikonfigurasi dengan cara yang sama dengan prosedur tersimpan entitas.
modelBuilder
.Entity<Post>()
.HasMany(p => p.Tags)
.WithMany(t => t.Posts)
.MapToStoredProcedures(s =>
s.Insert(i => i.HasName("add_post_tag")
.LeftKeyParameter(p => p.PostId, "post_id")
.RightKeyParameter(t => t.TagId, "tag_id"))
.Delete(d => d.HasName("remove_post_tag")
.LeftKeyParameter(p => p.PostId, "post_id")
.RightKeyParameter(t => t.TagId, "tag_id")));