Manajemen koneksi
Halaman ini menjelaskan perilaku Kerangka Kerja Entitas sehubungan dengan meneruskan koneksi ke konteks dan fungsionalitas Database.KoneksiIon. BUKA() API.
Meneruskan Koneksi ke Konteks
Perilaku untuk EF5 dan versi yang lebih lama
Ada dua konstruktor yang menerima koneksi:
public DbContext(DbConnection existingConnection, bool contextOwnsConnection)
public DbContext(DbConnection existingConnection, DbCompiledModel model, bool contextOwnsConnection)
Dimungkinkan untuk menggunakan ini tetapi Anda harus mengatasi beberapa batasan:
- Jika Anda meneruskan koneksi terbuka ke salah satu dari ini, maka pertama kali kerangka kerja mencoba menggunakannya, InvalidOperationException dilemparkan mengatakan tidak dapat membuka kembali koneksi yang sudah terbuka.
- Bendera contextOwns Koneksi ion ditafsirkan berarti apakah koneksi penyimpanan yang mendasar harus dibuang atau tidak saat konteks dibuang. Tetapi, terlepas dari pengaturan itu, koneksi penyimpanan selalu ditutup ketika konteks dibuang. Jadi, jika Anda memiliki lebih dari satu DbContext dengan koneksi yang sama, konteks mana pun yang dibuang terlebih dahulu akan menutup koneksi (demikian pula jika Anda telah mencampur koneksi ADO.NET yang ada dengan DbContext, DbContext akan selalu menutup koneksi ketika dibuang).
Dimungkinkan untuk mengatasi batasan pertama di atas dengan melewati koneksi tertutup dan hanya menjalankan kode yang akan membukanya setelah semua konteks dibuat:
using System.Collections.Generic;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.EntityClient;
using System.Linq;
namespace ConnectionManagementExamples
{
class ConnectionManagementExampleEF5
{
public static void TwoDbContextsOneConnection()
{
using (var context1 = new BloggingContext())
{
var conn =
((EntityConnection)
((IObjectContextAdapter)context1).ObjectContext.Connection)
.StoreConnection;
using (var context2 = new BloggingContext(conn, contextOwnsConnection: false))
{
context2.Database.ExecuteSqlCommand(
@"UPDATE Blogs SET Rating = 5" +
" WHERE Name LIKE '%Entity Framework%'");
var query = context1.Posts.Where(p => p.Blog.Rating > 5);
foreach (var post in query)
{
post.Title += "[Cool Blog]";
}
context1.SaveChanges();
}
}
}
}
}
Batasan kedua hanya berarti Anda perlu menahan diri dari membuang salah satu objek DbContext Anda sampai Anda siap untuk koneksi ditutup.
Perilaku dalam EF6 dan versi mendatang
Dalam versi EF6 dan yang akan datang, DbContext memiliki dua konstruktor yang sama tetapi tidak lagi mengharuskan koneksi yang diteruskan ke konstruktor ditutup ketika diterima. Jadi ini sekarang mungkin:
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.SqlClient;
using System.Linq;
using System.Transactions;
namespace ConnectionManagementExamples
{
class ConnectionManagementExample
{
public static void PassingAnOpenConnection()
{
using (var conn = new SqlConnection("{connectionString}"))
{
conn.Open();
var sqlCommand = new SqlCommand();
sqlCommand.Connection = conn;
sqlCommand.CommandText =
@"UPDATE Blogs SET Rating = 5" +
" WHERE Name LIKE '%Entity Framework%'";
sqlCommand.ExecuteNonQuery();
using (var context = new BloggingContext(conn, contextOwnsConnection: false))
{
var query = context.Posts.Where(p => p.Blog.Rating > 5);
foreach (var post in query)
{
post.Title += "[Cool Blog]";
}
context.SaveChanges();
}
var sqlCommand2 = new SqlCommand();
sqlCommand2.Connection = conn;
sqlCommand2.CommandText =
@"UPDATE Blogs SET Rating = 7" +
" WHERE Name LIKE '%Entity Framework Rocks%'";
sqlCommand2.ExecuteNonQuery();
}
}
}
}
Juga bendera contextOwns Koneksi ion sekarang mengontrol apakah koneksi ditutup atau tidak saat DbContext dibuang. Jadi dalam contoh di atas koneksi tidak ditutup ketika konteks dibuang (baris 32) seperti yang akan ada di versi EF sebelumnya, melainkan ketika koneksi itu sendiri dibuang (baris 40).
Tentu saja masih mungkin bagi DbContext untuk mengendalikan koneksi (cukup atur contextOwns Koneksi ion ke true atau gunakan salah satu konstruktor lain) jika Anda menginginkannya.
Catatan
Ada beberapa pertimbangan tambahan saat menggunakan transaksi dengan model baru ini. Untuk detailnya lihat Bekerja dengan Transaksi.
Database. Koneksi ion. Buka()
Perilaku untuk EF5 dan versi yang lebih lama
Dalam EF5 dan versi yang lebih lama ada bug sedih sehingga ObjectContext.KoneksiIon. Status tidak diperbarui untuk mencerminkan status sebenarnya dari koneksi penyimpanan yang mendasar. Misalnya, jika Anda menjalankan kode berikut, Anda dapat mengembalikan status Ditutup meskipun sebenarnya koneksi penyimpanan yang mendasar adalah Buka.
((IObjectContextAdapter)context).ObjectContext.Connection.State
Secara terpisah, jika Anda membuka koneksi database dengan memanggil Database. Koneksi ion. Buka() itu akan terbuka sampai saat berikutnya Anda menjalankan kueri atau memanggil apa pun yang memerlukan koneksi database (misalnya, SaveChanges()) tetapi setelah itu koneksi penyimpanan yang mendasar akan ditutup. Konteks kemudian akan membuka kembali dan menutup kembali koneksi kapan saja operasi database lain diperlukan:
using System;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.EntityClient;
namespace ConnectionManagementExamples
{
public class DatabaseOpenConnectionBehaviorEF5
{
public static void DatabaseOpenConnectionBehavior()
{
using (var context = new BloggingContext())
{
// At this point the underlying store connection is closed
context.Database.Connection.Open();
// Now the underlying store connection is open
// (though ObjectContext.Connection.State will report closed)
var blog = new Blog { /* Blog’s properties */ };
context.Blogs.Add(blog);
// The underlying store connection is still open
context.SaveChanges();
// After SaveChanges() the underlying store connection is closed
// Each SaveChanges() / query etc now opens and immediately closes
// the underlying store connection
blog = new Blog { /* Blog’s properties */ };
context.Blogs.Add(blog);
context.SaveChanges();
}
}
}
}
Perilaku dalam EF6 dan versi mendatang
Untuk EF6 dan versi mendatang, kami telah mengambil pendekatan bahwa jika kode panggilan memilih untuk membuka koneksi dengan memanggil konteks. Database. Koneksi ion. Open() kemudian memiliki alasan yang baik untuk melakukannya dan kerangka kerja akan mengasumsikan bahwa ia ingin mengontrol pembukaan dan penutupan koneksi dan tidak akan lagi menutup koneksi secara otomatis.
Catatan
Ini berpotensi menyebabkan koneksi yang terbuka untuk waktu yang lama sehingga gunakan dengan hati-hati.
Kami juga memperbarui kode sehingga ObjectContext. Koneksi ion. Status sekarang melacak status koneksi yang mendasar dengan benar.
using System;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Core.EntityClient;
using System.Data.Entity.Infrastructure;
namespace ConnectionManagementExamples
{
internal class DatabaseOpenConnectionBehaviorEF6
{
public static void DatabaseOpenConnectionBehavior()
{
using (var context = new BloggingContext())
{
// At this point the underlying store connection is closed
context.Database.Connection.Open();
// Now the underlying store connection is open and the
// ObjectContext.Connection.State correctly reports open too
var blog = new Blog { /* Blog’s properties */ };
context.Blogs.Add(blog);
context.SaveChanges();
// The underlying store connection remains open for the next operation
blog = new Blog { /* Blog’s properties */ };
context.Blogs.Add(blog);
context.SaveChanges();
// The underlying store connection is still open
} // The context is disposed – so now the underlying store connection is closed
}
}
}