Aracılığıyla paylaş


Basit Günlüğe Kaydetme

Bahşiş

Bu makalenin örneğini GitHub'dan indirebilirsiniz.

Entity Framework Core (EF Core) basit günlük kaydı, uygulama geliştirme ve hata ayıklama sırasında günlükleri kolayca almak için kullanılabilir. Bu günlük kaydı biçimi için en az yapılandırma gerekir ve ek NuGet paketi gerekmez.

Bahşiş

EF Core, daha fazla yapılandırma gerektiren ancak genellikle üretim uygulamalarında oturum açmak için daha uygun olan Microsoft.Extensions.Logging ile de tümleşir.

Yapılandırma

EF Core günlüklerine, DbContext örneği oluştururken her türden uygulamadan LogTo kullanılarak erişilebilir. Bu yapılandırma genellikle DbContext.OnConfiguring geçersiz kılma işlemiyle gerçekleştirilir. Örnek:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder.LogTo(Console.WriteLine);

Alternatif olarak, LogTo oluşturucuya geçirmek DbContext üzere bir DbContextOptions örnek oluşturulurken veya bir parçası AddDbContext olarak çağrılabilir.

Bahşiş

AddDbContext kullanıldığında veya DbContextOptions örneği DbContext oluşturucusna geçirildiğinde OnConfiguring hala çağrılır. Bu, DbContext'in nasıl yapılandırıldığından bağımsız olarak bağlam yapılandırmasını uygulamak için ideal bir yer olmasını sağlar.

Günlükleri yönlendirme

Konsolda günlüğe kaydetme

LogTo dizeyi kabul eden bir Action<T> temsilci gerektirir. EF Core, oluşturulan her günlük iletisi için bir dizeyle bu temsilciyi çağırır. Daha sonra verilen iletiyle bir şey yapmak temsilciye bağlı olur.

Console.WriteLine Yöntemi genellikle yukarıda gösterildiği gibi bu temsilci için kullanılır. Bu, her günlük iletisinin konsola yazılmasıyla sonuçlanıyor.

Hata ayıklama penceresinde günlüğe kaydetme

Debug.WriteLine , Çıktıyı Visual Studio'daki Hata Ayıklama penceresine veya diğer IDE'lere göndermek için kullanılabilir. Sınıfı yayın derlemeleri dışında derlendiğinden Debug lambda söz dizimi bu durumda kullanılmalıdır. Örnek:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder.LogTo(message => Debug.WriteLine(message));

Dosyaya günlük kaydı yapma

Bir dosyaya yazmak için dosya için bir veya benzer bir StreamWriter dosya oluşturulması gerekir. Yöntemi WriteLine daha sonra yukarıdaki diğer örneklerde olduğu gibi kullanılabilir. Bağlam atıldığında yazıcıyı atarak dosyanın temiz bir şekilde kapatıldığından emin olun. Örnek:

private readonly StreamWriter _logStream = new StreamWriter("mylog.txt", append: true);

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder.LogTo(_logStream.WriteLine);

public override void Dispose()
{
    base.Dispose();
    _logStream.Dispose();
}

public override async ValueTask DisposeAsync()
{
    await base.DisposeAsync();
    await _logStream.DisposeAsync();
}

Bahşiş

Üretim uygulamalarında dosyalara günlük kaydı için Microsoft.Extensions.Logging kullanmayı göz önünde bulundurun.

Ayrıntılı iletiler alınıyor

Hassas veriler

Varsayılan olarak, EF Core özel durum iletilerine hiçbir verinin değerini içermez. Bunun nedeni, bu tür verilerin gizli olması ve bir özel durum işlenmezse üretim kullanımında ortaya çıkarılabilmesidir.

Ancak, özellikle anahtarlar için veri değerlerini bilmek hata ayıklama sırasında çok yararlı olabilir. Bu, çağrısıyla EnableSensitiveDataLogging()EF Core'da etkinleştirilebilir. Örnek:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .LogTo(Console.WriteLine)
        .EnableSensitiveDataLogging();

Ayrıntılı sorgu özel durumları

Performans nedenleriyle EF Core, bir try-catch bloğundaki veritabanı sağlayıcısından bir değeri okumak için yapılan her çağrıyı sarmalamaz. Ancak, bu bazen özellikle veritabanı model tarafından izin verilmediğinde NULL döndürdüğünde tanılaması zor özel durumlarla sonuçlanıyor.

Bu ayarın açılması EnableDetailedErrors EF'in bu try-catch bloklarını tanıtmasına ve böylece daha ayrıntılı hatalar sağlamasına neden olur. Örnek:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .LogTo(Console.WriteLine)
        .EnableDetailedErrors();

Filtreleme

Günlük düzeyleri

Her EF Core günlük iletisi, sabit listesi tarafından tanımlanan bir düzeye LogLevel atanır. Varsayılan olarak, EF Core basit günlüğü her iletiyi Debug düzeyde veya daha yüksek bir düzeyde içerir. LogTo bazı iletileri filtrelemek için daha yüksek bir minimum düzey geçirilebilir. Örneğin, geçiş Information , veritabanı erişimi ve bazı temizlik iletileriyle sınırlı en az günlük kümesiyle sonuçlanır.

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder.LogTo(Console.WriteLine, LogLevel.Information);

Belirli iletiler

Her günlük iletisine bir EventIdatanır. Bu kimliklere ilişkisel özel iletiler için sınıfından veya sınıfından RelationalEventId erişilebilirCoreEventId. Veritabanı sağlayıcısının da benzer bir sınıfta sağlayıcıya özgü kimlikleri olabilir. Örneğin, SqlServerEventId SQL Server sağlayıcısı için.

LogTo yalnızca bir veya daha fazla olay kimlikleriyle ilişkili iletileri günlüğe kaydedecek şekilde yapılandırılabilir. Örneğin, yalnızca başlatılan veya atılan bağlama yönelik iletileri günlüğe kaydetmek için:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .LogTo(Console.WriteLine, new[] { CoreEventId.ContextDisposed, CoreEventId.ContextInitialized });

İleti kategorileri

Her günlük iletisi adlandırılmış hiyerarşik günlükçü kategorisine atanır. Kategoriler şunlardır:

Kategori İletiler
Microsoft.EntityFrameworkCore Tüm EF Core iletileri
Microsoft.EntityFrameworkCore.Database Tüm veritabanı etkileşimleri
Microsoft.EntityFrameworkCore.Database. Bağlan ion Veritabanı bağlantısının kullanımları
Microsoft.EntityFrameworkCore.Database.Command Veritabanı komutunun kullanımları
Microsoft.EntityFrameworkCore.Database.Transaction Veritabanı işleminin kullanımları
Microsoft.EntityFrameworkCore.Update Veritabanı etkileşimleri hariç varlıkları kaydetme
Microsoft.EntityFrameworkCore.Model Tüm model ve meta veri etkileşimleri
Microsoft.EntityFrameworkCore.Model.Validation Model doğrulaması
Microsoft.EntityFrameworkCore.Query Veritabanı etkileşimleri hariç sorgular
Microsoft.EntityFrameworkCore.Infrastructure Bağlam oluşturma gibi genel olaylar
Microsoft.EntityFrameworkCore.Scaffolding Veritabanı tersine mühendislik
Microsoft.EntityFrameworkCore.Migrations Geçişler
Microsoft.EntityFrameworkCore.ChangeTracking Değişiklik izleme etkileşimleri

LogTo yalnızca bir veya daha fazla kategorideki iletileri günlüğe kaydedecek şekilde yapılandırılabilir. Örneğin, yalnızca veritabanı etkileşimlerini günlüğe kaydetmek için:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .LogTo(Console.WriteLine, new[] { DbLoggerCategory.Database.Name });

DbLoggerCategory sınıfının bir kategoriyi bulmak için hiyerarşik bir API sağladığına ve dizeleri sabit kodlama gereğinden kaçındığını fark edin.

Kategoriler hiyerarşik olduğundan, kategoriyi Database kullanan bu örnek , Database.Commandve Database.Transactionalt kategorileri Database.Connectioniçin tüm iletileri içerir.

Özel filtreler

LogTo yukarıdaki filtreleme seçeneklerinden hiçbirinin yeterli olmadığı durumlarda özel bir filtrenin kullanılmasına izin verir. Örneğin, herhangi bir iletiyi hem düzeyde hem de daha yüksek bir düzeyde Information günlüğe kaydetmek ve bir bağlantıyı açıp kapatmak için iletiler:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .LogTo(
            Console.WriteLine,
            (eventId, logLevel) => logLevel >= LogLevel.Information
                                   || eventId == RelationalEventId.ConnectionOpened
                                   || eventId == RelationalEventId.ConnectionClosed);

Bahşiş

Özel filtreler kullanarak filtreleme veya burada gösterilen diğer seçeneklerden herhangi birini kullanmak, temsilcide LogTo filtrelemeden daha verimlidir. Bunun nedeni, filtre iletinin günlüğe kaydedilmemesi gerektiğini belirlerse günlük iletisinin oluşturulmamış olmasıdır.

Belirli iletiler için yapılandırma

EF Core ConfigureWarnings API'si, uygulamaların belirli bir olayla karşılaşıldığında ne olacağını değiştirmesine olanak tanır. Bu, aşağıdakiler için kullanılabilir:

  • Olayın günlüğe kaydedildiği günlük düzeyini değiştirme
  • Olayı günlüğe kaydetmeyi tamamen atlayın
  • Olay gerçekleştiğinde özel durum oluşturma

Olay için günlük düzeyini değiştirme

Önceki örnekte her iletiyi LogLevel.Information günlüğe kaydetmek için özel bir filtre ve için LogLevel.Debugtanımlanan iki olay kullanılmıştır. İki olayın Informationgünlük düzeyi Debug olarak değiştirilerek de aynı durum elde edilebilir:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .ConfigureWarnings(
            b => b.Log(
                (RelationalEventId.ConnectionOpened, LogLevel.Information),
                (RelationalEventId.ConnectionClosed, LogLevel.Information)))
        .LogTo(Console.WriteLine, LogLevel.Information);

Bir olayın günlüğe kaydedilmesini gizleme

Benzer şekilde, tek bir olay günlük kaydından gizlenebilir. Bu, özellikle gözden geçirilmiş ve anlaşılmış bir uyarıyı yoksaymak için kullanışlıdır. Örnek:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .ConfigureWarnings(b => b.Ignore(CoreEventId.DetachedLazyLoadingWarning))
        .LogTo(Console.WriteLine);

Olay için oluşturma

Son olarak, EF Core belirli bir olay için oluşturacak şekilde yapılandırılabilir. Bu, özellikle uyarıyı hataya dönüştürmede kullanışlıdır. (Aslında, yöntemin ConfigureWarnings özgün amacı budur, dolayısıyla addır.) Örneğin:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .ConfigureWarnings(b => b.Throw(RelationalEventId.MultipleCollectionIncludeWarning))
        .LogTo(Console.WriteLine);

İleti içeriği ve biçimlendirme

varsayılan içeriği LogTo birden çok satır arasında biçimlendirilir. İlk satır ileti meta verilerini içerir:

  • LogLevel Dört karakterli ön ek olarak
  • Geçerli kültür için biçimlendirilmiş yerel bir zaman damgası
  • EventId Üyeyi veya diğer EventId sınıflardan CoreEventId birini almak için kopyalanabilir/yapıştırılabilir formda, artı ham kimlik değeri
  • Yukarıda açıklandığı gibi olay kategorisi.

Örnek:

info: 10/6/2020 10:52:45.581 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
      Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      CREATE TABLE "Blogs" (
          "Id" INTEGER NOT NULL CONSTRAINT "PK_Blogs" PRIMARY KEY AUTOINCREMENT,
          "Name" INTEGER NOT NULL
      );
dbug: 10/6/2020 10:52:45.582 RelationalEventId.TransactionCommitting[20210] (Microsoft.EntityFrameworkCore.Database.Transaction)
      Committing transaction.
dbug: 10/6/2020 10:52:45.585 RelationalEventId.TransactionCommitted[20202] (Microsoft.EntityFrameworkCore.Database.Transaction)
      Committed transaction.

Bu içerik, aşağıdaki bölümlerde gösterildiği gibi 'den DbContextLoggerOptionsdeğerler geçirilerek özelleştirilebilir.

Bahşiş

Günlük biçimlendirmesi üzerinde daha fazla denetim için Microsoft.Extensions.Logging kullanmayı göz önünde bulundurun.

UTC saatini kullanma

Varsayılan olarak, zaman damgaları hata ayıklama sırasında yerel tüketim için tasarlanmıştır. Bunun yerine kültürden bağımsız UTC zaman damgalarını kullanmak, ancak diğer her şeyi aynı tutmak için kullanın DbContextLoggerOptions.DefaultWithUtcTime . Örnek:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder.LogTo(
        Console.WriteLine,
        LogLevel.Debug,
        DbContextLoggerOptions.DefaultWithUtcTime);

Bu örnek aşağıdaki günlük biçimlendirmesine neden olur:

info: 2020-10-06T17:55:39.0333701Z RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
      Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      CREATE TABLE "Blogs" (
          "Id" INTEGER NOT NULL CONSTRAINT "PK_Blogs" PRIMARY KEY AUTOINCREMENT,
          "Name" INTEGER NOT NULL
      );
dbug: 2020-10-06T17:55:39.0333892Z RelationalEventId.TransactionCommitting[20210] (Microsoft.EntityFrameworkCore.Database.Transaction)
      Committing transaction.
dbug: 2020-10-06T17:55:39.0351684Z RelationalEventId.TransactionCommitted[20202] (Microsoft.EntityFrameworkCore.Database.Transaction)
      Committed transaction.

Tek satırlı günlük kaydı

Bazen günlük iletisi başına tam olarak bir satır almak yararlı olabilir. Bu, tarafından DbContextLoggerOptions.SingleLineetkinleştirilebilir. Örnek:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder.LogTo(
        Console.WriteLine,
        LogLevel.Debug,
        DbContextLoggerOptions.DefaultWithLocalTime | DbContextLoggerOptions.SingleLine);

Bu örnek aşağıdaki günlük biçimlendirmesine neden olur:

info: 10/6/2020 10:52:45.723 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command) -> Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']CREATE TABLE "Blogs" (    "Id" INTEGER NOT NULL CONSTRAINT "PK_Blogs" PRIMARY KEY AUTOINCREMENT,    "Name" INTEGER NOT NULL);
dbug: 10/6/2020 10:52:45.723 RelationalEventId.TransactionCommitting[20210] (Microsoft.EntityFrameworkCore.Database.Transaction) -> Committing transaction.
dbug: 10/6/2020 10:52:45.725 RelationalEventId.TransactionCommitted[20202] (Microsoft.EntityFrameworkCore.Database.Transaction) -> Committed transaction.

Diğer içerik seçenekleri

içindeki DbContextLoggerOptions diğer bayraklar, günlüğe eklenen meta veri miktarını kırpmak için kullanılabilir. Bu, tek satırlı günlük kaydıyla birlikte yararlı olabilir. Örnek:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder.LogTo(
        Console.WriteLine,
        LogLevel.Debug,
        DbContextLoggerOptions.UtcTime | DbContextLoggerOptions.SingleLine);

Bu örnek aşağıdaki günlük biçimlendirmesine neden olur:

2020-10-06T17:52:45.7320362Z -> Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']CREATE TABLE "Blogs" (    "Id" INTEGER NOT NULL CONSTRAINT "PK_Blogs" PRIMARY KEY AUTOINCREMENT,    "Name" INTEGER NOT NULL);
2020-10-06T17:52:45.7320531Z -> Committing transaction.
2020-10-06T17:52:45.7339441Z -> Committed transaction.

EF6'dan taşıma

EF Core basit günlüğü EF6'dan Database.Log iki önemli şekilde farklıdır:

  • Günlük iletileri yalnızca veritabanı etkileşimleriyle sınırlı değildir
  • Günlük, bağlam başlatma zamanında yapılandırılmalıdır

İlk fark için, yukarıda açıklanan filtreleme hangi iletilerin günlüğe kaydedileceklerini sınırlamak için kullanılabilir.

İkinci fark, gerekli olmadığında günlük iletileri oluşturmayarak performansı iyileştirmeye yönelik kasıtlı bir değişikliktir. Ancak, üzerinde DbContext bir özellik oluşturup bunu yalnızca ayarlandığında kullanarak EF6'ya benzer bir Log davranış elde etmek yine de mümkündür. Örnek:

public Action<string> Log { get; set; }

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder.LogTo(s => Log?.Invoke(s));