DbContext ömrü, yapılandırma ve başlatma

Bu makalede bir DbContext örneğinin başlatılması ve yapılandırılması için temel desenler gösterilmektedir.

DbContext ömrü

DbContextÖrnek oluşturulduğunda başlar ve örnek DbContextzaman sona erer. Bir DbContext örnek, DbContextbiriş birimiiçin kullanılmak üzere tasarlanmıştır. Bu, örneğin yaşam süresinin DbContext genellikle çok kısa olduğu anlamına gelir.

İpucu

Yukarıdaki bağlantıdan Marwler teklifini teklif etmek için, "bir Iş birimi, veritabanını etkileyebilecek bir iş işlemi sırasında yaptığınız her şeyi izler. İşiniz bittiğinde, işinizi sonucu olarak veritabanını değiştirmek için yapılması gereken her şeyi belirler. "

Entity Framework Core (EF Core) kullanılırken tipik bir iş birimi şunları içerir:

Önemli

  • Kullanıldıktan sonra DbContext 'i atmak çok önemlidir. Bu, hem yönetilmeyen kaynakların serbest bırakılmasını hem de örneğin başvurulması durumunda bellek sızıntılarını engellemek için tüm olayların veya diğer kancaların kaydının silinmesini sağlar.
  • DbContext iş parçacığı açısından güvenli değil. İş parçacıkları arasında bağlamlar paylaşmayın. Bağlam örneğini kullanmaya devam etmeden önce tüm zaman uyumsuz çağrıları beklediğinizden emin olun.
  • EF Core kod tarafından oluşturulan bir InvalidOperationException , bağlamı kurtarılamaz duruma yerleştirebilir. Bu tür özel durumlar, bir program hatası olduğunu gösterir ve kurtarılmak üzere tasarlanmamıştır.

ASP.NET Core için bağımlılık ekleme sırasında DbContext

Birçok Web uygulamasında, her HTTP isteği tek bir iş birimine karşılık gelir. Böylece bağlam ömrü, Web uygulamaları için iyi bir varsayılan değer ister.

ASP.NET Core uygulamalar, bağımlılık ekleme kullanılarak yapılandırılır. Bu yapılandırmaya EF Core yönteminde Adddbcontext kullanılarak eklenebilir Startup.cs . Örnek:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();

    services.AddDbContext<ApplicationDbContext>(
        options => options.UseSqlServer("name=ConnectionStrings:DefaultConnection"));
}

bu örnek DbContextApplicationDbContext , ASP.NET Core uygulama hizmeti sağlayıcısında (deyişle bağımlılık ekleme kapsayıcısı) kapsamlı hizmet olarak adlandırılan bir alt sınıfı kaydeder. bağlam, SQL Server veritabanı sağlayıcısını kullanacak şekilde yapılandırılır ve ASP.NET Core yapılandırmasından bağlantı dizesini okur. Genellikle yapılan çağrının nerede yapılmadığına bir önemi yoktur AddDbContext .

ApplicationDbContextSınıf, bir parametreli ortak oluşturucuyu kullanıma sunmalıdır DbContextOptions<ApplicationDbContext> . Bu, ' den bağlam yapılandırması ' a AddDbContext geçirilir DbContext . Örnek:

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }
}

ApplicationDbContextdaha sonra, ASP.NET Core denetleyicilerinde veya diğer hizmetlerde oluşturucu ekleme yoluyla kullanılabilir. Örnek:

public class MyController
{
    private readonly ApplicationDbContext _context;

    public MyController(ApplicationDbContext context)
    {
        _context = context;
    }
}

Nihai sonuç, ApplicationDbContext her istek için oluşturulan bir örneğidir ve istek sona erdiğinde atılmadan önce bir çalışma birimi gerçekleştirmek üzere denetleyiciye geçirilir.

Yapılandırma seçenekleri hakkında daha fazla bilgi edinmek için bu makaleyi okuyun. ayrıca, ASP.NET Core yapılandırma ve bağımlılık ekleme hakkında daha fazla bilgi için ASP.NET Core ASP.NET Core ve bağımlılık ekleme' de uygulama başlatma bölümüne bakın.

' New ' ile basit DbContext başlatması

DbContext örnekler, örneğin C# içinde olan normal .NET yöntemi içinde oluşturulabilir new . Yapılandırma, yöntemi geçersiz kılarak OnConfiguring veya oluşturucuya seçenekler geçirerek gerçekleştirilebilir. Örnek:

public class ApplicationDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Test");
    }
}

Bu model Ayrıca, Oluşturucu aracılığıyla bağlantı dizesi gibi yapılandırmayı kolayca geçirmeye de olanak sağlar DbContext . Örnek:

public class ApplicationDbContext : DbContext
{
    private readonly string _connectionString;

    public ApplicationDbContext(string connectionString)
    {
        _connectionString = connectionString;
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(_connectionString);
    }
}

Alternatif olarak, DbContextOptionsBuilderDbContextOptions daha sonra oluşturucuya geçirilecek bir nesne oluşturmak için kullanılabilir DbContext . Bu, DbContext bağımlılık ekleme için yapılandırılmış bir yöneticinin açıkça oluşturulmasını sağlar. örneğin, ApplicationDbContext yukarıdaki ASP.NET Core web uygulamaları için tanımlanan kullanıldığında:

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }
}

DbContextOptionsOluşturulabilir ve Oluşturucu açık bir şekilde çağrılabilir:

var contextOptions = new DbContextOptionsBuilder<ApplicationDbContext>()
    .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Test")
    .Options;

using var context = new ApplicationDbContext(contextOptions);

DbContext fabrikası kullanma (ör. Blazor için)

bazı uygulama türleri (örn. ASP.NET Core Blazor) bağımlılık ekleme işlemini kullanır, ancak istenen ömür ile hizalanan bir hizmet kapsamı oluşturmaz . Böyle bir hizalama mevcut olsa bile, uygulamanın bu kapsam içinde birden çok iş birimi gerçekleştirmesi gerekebilir. Örneğin, tek bir HTTP isteği içindeki birden çok iş birimi.

Bu durumlarda, örnek oluşturmak için bir fabrikası kaydetmek üzere Adddbcontextfactory kullanılabilir . Örnek:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContextFactory<ApplicationDbContext>(
        options =>
            options.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Test"));
}

ApplicationDbContextSınıf, bir parametreli ortak oluşturucuyu kullanıma sunmalıdır DbContextOptions<ApplicationDbContext> . bu, yukarıdaki geleneksel ASP.NET Core bölümünde kullanılan modeldir.

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }
}

DbContextFactoryDaha sonra fabrika, diğer hizmetlerde Oluşturucu ekleme yoluyla kullanılabilir. Örnek:

private readonly IDbContextFactory<ApplicationDbContext> _contextFactory;

public MyController(IDbContextFactory<ApplicationDbContext> contextFactory)
{
    _contextFactory = contextFactory;
}

Eklenen fabrika daha sonra hizmet kodunda DbContext örnekleri oluşturmak için kullanılabilir. Örnek:

public void DoSomething()
{
    using (var context = _contextFactory.CreateDbContext())
    {
        // ...
    }
}

DbContextBu şekilde oluşturulan örneklerin, uygulamanın hizmet sağlayıcısı tarafından DbContext yönetilmediğini ve bu nedenle uygulama tarafından atılmalıdır.

Blazor ile EF Core kullanma hakkında daha fazla bilgi için bkz. Entity Framework Core ASP.NET Core Blazor Server .

DbContextOptions

Tüm yapılandırma için başlangıç noktası DbContextDbContext' dır. Bu oluşturucuyu almanın üç yolu vardır:

  • AddDbContextVe ile ilgili Yöntemler
  • 'Ndaki OnConfiguring
  • İle açıkça oluşturulur new

Bunların her birine örnek olarak, önceki bölümlerde gösterilmiştir. Oluşturucunun nereden geldiğini göz önüne alarak aynı yapılandırma uygulanabilir. Ayrıca, OnConfiguring bağlamın nasıl oluşturulduğuna bakılmaksızın her zaman çağrılır. Bu OnConfiguring , kullanılırken bile ek yapılandırma gerçekleştirmek için kullanılabilir AddDbContext .

Veritabanı sağlayıcısını yapılandırma

Her DbContext örnek tek bir veritabanı sağlayıcısını kullanacak şekilde yapılandırılmalıdır. (Bir DbContext alt tür farklı örnekleri farklı veritabanı sağlayıcılarıyla kullanılabilir, ancak tek bir örnek yalnızca bir tane kullanılmalıdır.) Bir veritabanı sağlayıcısı belirli bir çağrı kullanılarak yapılandırılır Use* . örneğin, SQL Server veritabanı sağlayıcısını kullanmak için:

public class ApplicationDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Test");
    }
}

Bu Use* Yöntemler, veritabanı sağlayıcısı tarafından uygulanan genişletme yöntemleridir. bu, uzantı yöntemi kullanılmadan önce veritabanı sağlayıcısı NuGet paketinin yüklenmesi gereken anlamına gelir.

İpucu

EF Core veritabanı sağlayıcıları uzantı yöntemlerininkapsamlı kullanımını yapar. derleyici bir yöntemin bulunamadığını gösteriyorsa, sağlayıcının NuGet paketinin yüklü olduğundan ve kodunuzda bulunduğundan emin olun using Microsoft.EntityFrameworkCore; .

Aşağıdaki tabloda, yaygın veritabanı sağlayıcılarının örnekleri verilmiştir.

Veritabanı sistemi Örnek yapılandırma NuGet paketi
SQL Server veya Azure SQL .UseSqlServer(connectionString) Microsoft. EntityFrameworkCore. SqlServer
Azure Cosmos DB .UseCosmos(connectionString, databaseName) Microsoft. EntityFrameworkCore. Cosmos
SQLite .UseSqlite(connectionString) Microsoft. EntityFrameworkCore. SQLite
Bellek içi veritabanı EF Core .UseInMemoryDatabase(databaseName) Microsoft. EntityFrameworkCore. InMemory
PostgreSQL .UseNpgsql(connectionString) Npgsql. EntityFrameworkCore. PostgreSQL
MySQL/MariaDB * .UseMySql(connectionString) Pomelo. EntityFrameworkCore. MySql
Oracle* .UseOracle(connectionString) Oracle. EntityFrameworkCore

* Bu veritabanı sağlayıcıları Microsoft tarafından sevk edilmez. Veritabanı sağlayıcıları hakkında daha fazla bilgi için bkz. veritabanı sağlayıcıları .

Uyarı

EF Core bellek içi veritabanı, üretim kullanımı için tasarlanmamıştır. Ayrıca, sınama için bile en iyi seçim olmayabilir. Daha fazla bilgi için, bkz. EF Core kullanan test kodu .

EF Core ile bağlantı dizelerini kullanma hakkında daha fazla bilgi için bkz. bağlantı dizeleri .

Veritabanı sağlayıcısına özgü isteğe bağlı yapılandırma, sağlayıcıya özgü ek bir oluşturucuda gerçekleştirilir. Örneğin, Azure SQL bağlanırken bağlantı dayanıklılığı için yeniden denemeleri yapılandırmak üzere Enableretryonfailure kullanma:

public class ApplicationDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder
            .UseSqlServer(
                @"Server=(localdb)\mssqllocaldb;Database=Test",
                providerOptions => { providerOptions.EnableRetryOnFailure(); });
    }
}

İpucu

SQL Server ve Azure SQL için aynı veritabanı sağlayıcısı kullanılır. Ancak, SQL Azure bağlanırken bağlantı dayanıklılığı kullanılması önerilir.

Sağlayıcıya özgü yapılandırma hakkında daha fazla bilgi için bkz. veritabanı sağlayıcıları .

Diğer DbContext yapılandırması

Diğer DbContext yapılandırma, çağrı yapmadan önce veya sonra zincirlenebilir (hiçbir fark yapmaz) Use* . Örneğin, hassas veri günlüğünü açmak için:

public class ApplicationDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder
            .EnableSensitiveDataLogging()
            .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Test");
    }
}

Aşağıdaki tabloda, üzerinde çağrılan ortak yöntemlerin örnekleri verilmiştir DbContextOptionsBuilder .

DbContextOptionsBuilder yöntemi Ne yapar? Daha fazla bilgi edinin
UseQueryTrackingBehavior Sorgular için varsayılan izleme davranışını ayarlar Sorgu Izleme davranışı
Günlüğe kaydetme EF Core günlüklerini almanın basit bir yolu (EF Core 5,0 ve üzeri) Günlüğe kaydetme, olaylar ve Tanılamalar
UseLoggerFactory Bir Microsoft.Extensions.Logging fabrikası kaydeder Günlüğe kaydetme, olaylar ve Tanılamalar
EnableSensitiveDataLogging Özel durumlar ve günlüğe kaydetmek için uygulama verilerini içerir Günlüğe kaydetme, olaylar ve Tanılamalar
EnableDetailedErrors Daha ayrıntılı sorgu hataları (performans masrafına) Günlüğe kaydetme, olaylar ve Tanılamalar
Configureuyarıları Uyarılar ve diğer olaylar için yoksayın veya throw Günlüğe kaydetme, olaylar ve Tanılamalar
Addyakalayıcılar EF Core yakalayıcılar kaydettirir Günlüğe kaydetme, olaylar ve Tanılamalar
Uselazyloadingproxy 'Leri Yavaş yükleme için dinamik proxy 'leri kullanma Geç yükleme
Usechangetrackingproxy 'Leri Değişiklik izleme için dinamik proxy 'leri kullanma Çok yakında...

Not

uselazyloadingproxy 'ler ve usechangetrackingproxy 'ler , Microsoft. entityframeworkcore. proxy NuGet paketindeki uzantı yöntemlerdir. Bu tür ". Usebir () "çağrısı, diğer paketlerde bulunan EF Core uzantılarını yapılandırmak ve/veya kullanmak için önerilen yoldur.

DbContextOptions rakam DbContextOptions<TContext>

DbContextBir öğesini kabul eden çoğu alt sınıfın DbContextOptionsDbContextDbContextOptions<TContext> çeşitlemesi kullanması gerekir. Örnek:

public sealed class SealedApplicationDbContext : DbContext
{
    public SealedApplicationDbContext(DbContextOptions<SealedApplicationDbContext> contextOptions)
        : base(contextOptions)
    {
    }
}

Bu, DbContext birden çok alt tür kaydedildiğinde bile, belirli alt türe yönelik doğru seçeneklerin bağımlılık ekleme işleminden çözümlenmesini sağlar DbContext .

İpucu

DbContext 'in mühürlenmesi gerekmez, ancak mührü devralmak için tasarlanmayan sınıflar için en iyi uygulamadır.

Ancak, DbContext alt tür kendisinden devralınması amaçlanıyorsa, genel olmayan bir korumalı oluşturucuyu kullanıma sunmalıdır DbContextOptions . Örnek:

public abstract class ApplicationDbContextBase : DbContext
{
    protected ApplicationDbContextBase(DbContextOptions contextOptions)
        : base(contextOptions)
    {
    }
}

Bu, birden fazla somut alt sınıfın, farklı genel örneklerini kullanarak bu temel oluşturucuyu çağırmasını sağlar DbContextOptions<TContext> . Örnek:

public sealed class ApplicationDbContext1 : ApplicationDbContextBase
{
    public ApplicationDbContext1(DbContextOptions<ApplicationDbContext1> contextOptions)
        : base(contextOptions)
    {
    }
}

public sealed class ApplicationDbContext2 : ApplicationDbContextBase
{
    public ApplicationDbContext2(DbContextOptions<ApplicationDbContext2> contextOptions)
        : base(contextOptions)
    {
    }
}

Bu, doğrudan devralırken olduğu gibi tamamen aynı düzende olduğuna dikkat edin DbContext . Diğer bir deyişle, DbContext oluşturucunun kendisi bu nedenle genel olmayan bir değer kabul eder DbContextOptions .

DbContextHem örneklenmiş hem de Devralınanı amaçlanan bir alt sınıf, her iki Oluşturucu biçimini kullanıma sunmalıdır. Örnek:

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> contextOptions)
        : base(contextOptions)
    {
    }

    protected ApplicationDbContext(DbContextOptions contextOptions)
        : base(contextOptions)
    {
    }
}

Tasarım zamanı DbContext yapılandırması

EF Core geçişleri gibi tasarım zamanı araçlarının , uygulamanın varlık türleriyle ilgili ayrıntıları ve bir veritabanı şemasına nasıl eşlendikleri hakkında bilgi toplamak için bir türün çalışma örneğini bulması ve oluşturabilmeleri gerekir. EF Core Bu işlem, araç, DbContext çalışma zamanında nasıl yapılandırılacağından benzer şekilde yapılandırılacak şekilde kolayca oluşturabileceğiniz sürece otomatik olabilir.

İçin gerekli yapılandırma bilgilerini sağlayan herhangi DbContext bir desen çalışma zamanında çalışsa da, tasarım zamanı için kullanılması gereken Araçlar DbContext yalnızca sınırlı sayıda desenle çalışabilir. Bunlar Tasarım zamanı bağlam oluşturmabölümünde daha ayrıntılı olarak ele alınmıştır.

DbContext iş parçacığı sorunlarından kaçınma

Entity Framework Core, aynı örnekte çalıştırılan birden çok paralel işlemi desteklemez DbContext . Bu, zaman uyumsuz sorguların paralel yürütmesini ve birden çok iş parçacığından açık olan eşzamanlı kullanımı içerir. Bu nedenle, her zaman await zaman uyumsuz çağrılar hemen, DbContext paralel olarak yürütülen işlemler için ayrı örnekler kullanır.

EF Core aynı anda bir örneği kullanma girişimi algıladığında şöyle bir DbContextInvalidOperationException ileti görürsünüz:

Önceki bir işlem tamamlanmadan önce bu bağlamda ikinci bir işlem başlatıldı. Bu genellikle aynı DbContext örneğini kullanan farklı iş parçacıklarından kaynaklanır, ancak örnek üyelerin iş parçacığı güvenli olduğu garanti edilmez.

Eşzamanlı erişim algılanmadıysa, tanımsız davranışa, uygulama kilitlenmelerine ve veri bozulmasına neden olabilir.

Aynı örnekte yanlışlıkla eşzamanlı erişime neden olabilecek yaygın hatalar vardır DbContext :

Zaman uyumsuz işlem sınırları

Zaman uyumsuz yöntemler, EF Core engellenmeyen bir şekilde veritabanına erişen işlemler başlatmasını etkinleştirir. Ancak bir arayan, bu yöntemlerin birinin tamamlanmasını beklemez ve üzerinde başka işlemler gerçekleştirmeye devam etmez, DbContext durumu DbContext (ve büyük olasılıkla) bozulmuş olabilir.

Her zaman zaman uyumsuz yöntemleri hemen EF Core.

DbContext örneklerini bağımlılık ekleme yoluyla örtük olarak paylaşma

AddDbContextGenişletme yöntemi, DbContext Varsayılan olarak AddDbContext sahip türleri kaydeder.

belirli bir zamanda her istemci isteğini yürüten tek bir iş parçacığı olduğundan ve her istek ayrı bir bağımlılık ekleme kapsamı (ve dolayısıyla ayrı bir örnek) aldığından, çoğu ASP.NET Core uygulamalarda eşzamanlı erişim sorunlarından daha güvenlidir DbContext . Blazor sunucusu barındırma modeli için, Blazor Kullanıcı devresini sürdürmek için bir mantıksal istek kullanılır ve bu nedenle varsayılan ekleme kapsamı kullanılırsa Kullanıcı devresi başına yalnızca bir kapsamlı DbContext örneği kullanılabilir.

Birden çok iş parçacığını paralel olarak yürüten tüm kodlar, DbContext örneklere aynı anda erişilmemesini sağlamalıdır.

Bağımlılık ekleme 'yi kullanarak bu, bağlamı kapsam olarak kaydederek ve her bir iş parçacığı için kapsam (kullanılarak) oluşturarak IServiceScopeFactory ya da DbContext geçici olarak kaydederek ( AddDbContext bir parametre alan ' nin aşırı yüklemesini kullanarak ServiceLifetime ) elde edilebilir.

Daha fazla okuma

  • Dı kullanma hakkında daha fazla bilgi edinmek için bağımlılık ekleme konusunu okuyun.
  • Daha fazla bilgi için testi okuyun.