Aracılığıyla paylaş


Bağlantı yönetimi

Bu sayfada, Database.Bağlan bağlamı ve işlevselliğine bağlantı geçirmeyle ilgili Entity Framework'ün davranışı açıklanmaktadırIyon. Open() API'si.

bağlama Bağlan geçirme

EF5 ve önceki sürümler için davranış

Bağlantıları kabul eden iki oluşturucu vardır:

public DbContext(DbConnection existingConnection, bool contextOwnsConnection)
public DbContext(DbConnection existingConnection, DbCompiledModel model, bool contextOwnsConnection)

Bunları kullanmak mümkündür, ancak birkaç sınırlamaya geçici bir çözüm bulmak gerekir:

  1. Bunlardan herhangi biriyle açık bir bağlantı geçirirseniz, çerçeve onu ilk kez kullanmaya çalıştığında, zaten açık olan bir bağlantıyı yeniden açamayacağını belirten bir InvalidOperationException oluşturulur.
  2. contextOwns Bağlan ion bayrağı, bağlam atıldığında temel alınan depo bağlantısının atılıp atılmayacağı anlamına gelir. Ancak, bu ayardan bağımsız olarak, bağlam atıldığında depo bağlantısı her zaman kapatılır. Bu nedenle, aynı bağlantıya sahip birden fazla DbContext'iniz varsa, ilk olarak atılan bağlam bağlantıyı kapatır (benzer şekilde, mevcut bir ADO.NET bağlantısını bir DbContext ile karıştırdıysanız, DbContext atıldığında bağlantıyı her zaman kapatır).

Kapalı bir bağlantı geçirerek ve yalnızca tüm bağlamlar oluşturulduktan sonra onu açacak kodu yürüterek yukarıdaki ilk sınırlamaya geçici bir çözüm bulmak mümkündür:

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();
                }
            }
        }
    }
}

İkinci sınırlama, bağlantının kapatılmasına hazır olana kadar DbContext nesnelerinizden herhangi birini yok etmekten kaçınmanız gerektiği anlamına gelir.

EF6 ve sonraki sürümlerde davranış

EF6 ve sonraki sürümlerde DbContext aynı iki oluşturucuya sahiptir, ancak artık oluşturucuya geçirilen bağlantının alındığında kapatılmasını gerektirmez. Bu nedenle bu artık mümkündür:

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();
            }
        }
    }
}

Ayrıca contextOwns Bağlan ion bayrağı artık DbContext atıldığında bağlantının hem kapatılıp kapatılmayacağını hem de atılıp atılmayacağını denetler. Bu nedenle yukarıdaki örnekte, bağlam ef'in önceki sürümlerinde olduğu gibi atıldığında (32. satır) bağlantı kapatılmaz, bağlantının kendisi atıldığında (40. satır) kapatılmaz.

Dilerseniz DbContext'in bağlantının denetimini alması (contextOwns Bağlan ion değerini true olarak ayarlamanız veya diğer oluşturuculardan birini kullanmanız da mümkündür.

Dekont

Bu yeni modelle işlemleri kullanırken dikkat edilmesi gereken bazı ek noktalar vardır. Ayrıntılar için bkz . İşlemlerle Çalışma.

Veritabanı. Bağlan. Open()

EF5 ve önceki sürümler için davranış

EF5 ve önceki sürümlerde ObjectContext.BağlanIyon. Durum, temel alınan depo bağlantısının gerçek durumunu yansıtacak şekilde güncelleştirilmedi. Örneğin, aşağıdaki kodu yürütürseniz, temel alınan depo bağlantısı Açık olsa bile Kapalı durumu döndürülebilir.

((IObjectContextAdapter)context).ObjectContext.Connection.State

Ayrıca, Veritabanı'nı çağırarak veritabanı bağlantısını açarsanız. Bağlan. Open(), bir sonraki sorguyu yürütene veya veritabanı bağlantısı gerektiren herhangi bir şeyi (örneğin, SaveChanges()) çağırana kadar açık olur, ancak bundan sonra temel alınan depo bağlantısı kapatılır. Bağlam daha sonra başka bir veritabanı işlemi gerektiğinde bağlantıyı yeniden açar ve yeniden kapatır:

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();
            }
        }
    }
}

EF6 ve sonraki sürümlerde davranış

EF6 ve gelecekteki sürümler için, çağıran kod bağlamı çağırarak bağlantıyı açmayı seçerse yaklaşımını benimsedik. Veritabanı. Bağlan. Open(), bunu yapmak için iyi bir nedene sahiptir ve çerçeve, bağlantının açılması ve kapatılması üzerinde denetim sahibi olmak istediğini ve artık bağlantıyı otomatik olarak kapatmayacağını varsayar.

Dekont

Bu, uzun süre açık olan bağlantılara yol açabilir, bu nedenle dikkatli kullanın.

Ayrıca kodu ObjectContext olarak güncelleştirdik. Bağlan. Durum artık temel alınan bağlantının durumunu doğru şekilde izler.

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
        }
    }
}