Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
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.
Tavsiye
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.
Konfigürasyon
EF Core günlüklerine, LogTo kullanımı aracılığıyla herhangi bir uygulama türünden erişilebilir. Bu yapılandırma genellikle bir geçersiz kılma işleminde DbContext.OnConfiguring yapılır. Örneğin:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.LogTo(Console.WriteLine);
Alternatif olarak, LogTo, AddDbContext'in bir parçası olarak veya DbContextOptions oluşturucusuna geçmek üzere bir DbContext örneği oluşturulurken çağrılabilir.
Tavsiye
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.
Kayıtları yönlendirme
Konsola loglama
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. Sonra temsilciye, verilen mesajla ilgili bir şey yapma görevi düşer.
Console.WriteLine Yöntemi genellikle yukarıda gösterildiği gibi bu temsilci için kullanılır. Bunun sonucunda her ileti konsola yazılır.
Hata ayıklama penceresine kayıt yapma
Debug.WriteLine , Çıktıyı Visual Studio'daki Hata Ayıklama penceresine veya diğer IDE'lere göndermek için kullanılabilir. Bu durumda lambda söz dizimi kullanılmalıdır çünkü Debug sınıfı dağıtım derlemelerine dahil edilmemiştir. Örneğin:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.LogTo(message => Debug.WriteLine(message));
Dosyaya kaydetme
Bir dosyaya yazmak için, dosya için bir StreamWriter veya benzeri bir şey oluşturulması gerekir. Yöntemi WriteLine daha sonra yukarıdaki diğer örneklerde olduğu gibi kullanılabilir. Bağlam serbest bırakıldığında yazarı da yok ederek dosyanın düzgün şekilde kapatıldığından emin olun. Örneğin:
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();
}
Tavsiye
Dosyalara günlük kaydı yapmak için üretim uygulamalarında Microsoft.Extensions.Logging kullanmayı düşünün.
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. EF Core'da EnableSensitiveDataLogging() çağrılarak etkinleştirilebilir. Örneğin:
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. Örneğin:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.LogTo(Console.WriteLine)
.EnableDetailedErrors();
Filtreleme
Günlük düzeyleri
Her EF Core günlük iletisi, bir enum tarafından tanımlanan bir düzeye LogLevel atanır. Varsayılan olarak, EF Core basit günlüğü, Debug düzeyindeki veya daha yüksek düzeydeki tüm iletileri içerir.
LogTo bazı iletileri elemek için daha yüksek bir eşik değerine ayarlanabilir. Örneğin, Information kullanıldığında, veritabanı erişimi ve bazı bakım mesajlarıyla sınırlı en az günlük kümesine ulaşılır.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.LogTo(Console.WriteLine, LogLevel.Information);
Belirli iletiler
Her günlük iletisine bir EventIdatanır. Bu kimlikler, ilişkisel özel iletilere erişim için CoreEventId sınıfı veya RelationalEventId sınıfı üzerinden erişilebilir. 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, başlatılan veya sonlandırılan bağlama yönelik iletileri yalnızca 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 | Mesajlar |
|---|---|
| Microsoft.EntityFrameworkCore | Tüm EF Core iletileri |
| Microsoft.EntityFrameworkCore.Database | Tüm veritabanı etkileşimleri |
| Microsoft.EntityFrameworkCore.Database.Connection | Veritabanı bağlantısının kullanımları |
| Microsoft.EntityFrameworkCore.Veritabanı.Komut | 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 | Göçler |
| Microsoft.EntityFrameworkCore.ChangeTracking | Değişiklik izleme etkinlikleri |
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.Connectionve Database.Commandalt kategorileri Database.Transactioniç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, Information düzeyinde veya daha yüksek düzeyde herhangi bir iletiyi kaydetmek ve bir bağlantıyı açma veya kapatma iletilerini günlüğe kaydetmek için:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.LogTo(
Console.WriteLine,
(eventId, logLevel) => logLevel >= LogLevel.Information
|| eventId == RelationalEventId.ConnectionOpened
|| eventId == RelationalEventId.ConnectionClosed);
Tavsiye
Ö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 iletisi hiç oluşturulmaz.
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 kaydedildiği log seviyesini değiştir.
- Olayı günlüğe kaydetmeyi tamamen atlayın
- Olay gerçekleştiğinde istisna fırlatın
Olay için kayıt seviyesini değiştirme
Önceki örnekte, her iletiyi LogLevel.Information'de günlüğe kaydetmek için özel bir filtre ve LogLevel.Debug için tanımlanan iki olay kullanılmıştır. Aynı durum, iki Debug olayının günlük düzeyini Information olarak değiştirerek de 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. Özellikle gözden geçirilmiş ve idrak edilmiş bir uyarıyı yoksaymak için kullanışlıdır. Örneğin:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.ConfigureWarnings(b => b.Ignore(CoreEventId.DetachedLazyLoadingWarning))
.LogTo(Console.WriteLine);
Etkinlik düzenlemek
Son olarak, EF Core belirli bir olay için istisna fırlatacak ş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.) Mesela:
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çerik LogTo çok sayıda satıra yayılarak biçimlendirilmiştir. İ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ı
- Kopyalanabilir/yapıştırılabilir formda EventId, CoreEventId veya diğer
EventIdsınıflardan bir üye elde etmek için ve ham kimlik değeri ile. - Yukarıda açıklandığı gibi olay kategorisi.
Örneğin:
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.
Tavsiye
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. DbContextLoggerOptions.DefaultWithUtcTime kullanarak kültürden bağımsız UTC zaman damgaları kullanın, ancak diğer her şeyi aynı tutun. Örneğin:
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, DbContextLoggerOptions.SingleLine tarafından etkinleştirilebilir. Örneğin:
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
Diğer bayraklar DbContextLoggerOptions içinde, günlüğe eklenen meta veri miktarını azaltmak için kullanılabilir. Tek satırlı günlük kaydıyla birlikte bu çok yararlı olabilir. Örneğin:
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 geçiş
EF Core basit günlüğü, EF6'nın Database.Log ile 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 Log bir özellik oluşturup bunu yalnızca ayarlandığında kullanarak EF6'ya benzer bir DbContext davranış elde etmek yine de mümkündür. Örneğin:
public Action<string> Log { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.LogTo(s => Log?.Invoke(s));