MCDLabs.Utility.SqlHelper.TableHint 1.0.3

dotnet add package MCDLabs.Utility.SqlHelper.TableHint --version 1.0.3
                    
NuGet\Install-Package MCDLabs.Utility.SqlHelper.TableHint -Version 1.0.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="MCDLabs.Utility.SqlHelper.TableHint" Version="1.0.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="MCDLabs.Utility.SqlHelper.TableHint" Version="1.0.3" />
                    
Directory.Packages.props
<PackageReference Include="MCDLabs.Utility.SqlHelper.TableHint" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add MCDLabs.Utility.SqlHelper.TableHint --version 1.0.3
                    
#r "nuget: MCDLabs.Utility.SqlHelper.TableHint, 1.0.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package MCDLabs.Utility.SqlHelper.TableHint@1.0.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=MCDLabs.Utility.SqlHelper.TableHint&version=1.0.3
                    
Install as a Cake Addin
#tool nuget:?package=MCDLabs.Utility.SqlHelper.TableHint&version=1.0.3
                    
Install as a Cake Tool

MCDLabs.Utility.SqlHelper.TableHint

NuGet Version License MERTCANDULDUL

Açıklama

MCDLabs.Utility.SqlHelper.TableHint, Entity Framework Core 9.0+ ile SQL Server table hints (tablo ipuçları) kullanmanızı sağlayan güçlü bir kütüphanedir. Bu kütüphane, LINQ sorguları yazarken doğrudan SQL Server table hints uygulamanıza olanak tanır ve sorgu performansını optimize etmenize yardımcı olur.

Özellikler

✅ Entity Framework Core 9.0+ Desteği - En yeni EF Core sürümleri ile tam uyumluluk
✅ Fluent API - Sorgulanabilir nesneler üzerinde doğrudan hint uygulama
✅ Kapsamlı Hint Desteği - 20+ SQL Server table hint
✅ Async/Sync Destek - Hem senkron hem de asenkron sorgulamayı destekler
✅ Performans Optimizasyonu - Sorgu planlayıcısına ipuçları vererek performansı artırın
✅ InMemory Provider Uyarısı - InMemory provider kullananlar için otomatik hata bildirimi

Desteklenen Table Hints

Hint Açıklama
FORCESCAN Sorgu planlayıcısını tablo taraması yapmaya zorlar
FORCESEEK Sorgu planlayıcısını dizin araması yapmaya zorlar
HOLDLOCK Satırı sorgu bitene kadar kilitli tutar
NOLOCK Kilit olmadan okuma (Dirty Read izin verir)
NOWAIT Kilit beklemeyi devre dışı bırakır
PAGLOCK Sayfa düzeyinde kilitler
ROWLOCK Satır düzeyinde kilitler
TABLOCK Tablo düzeyinde paylaşımlı kilit
TABLOCKX Tablo düzeyinde özel kilit
READCOMMITTED READ COMMITTED izolasyon seviyesi
READUNCOMMITTED READ UNCOMMITTED izolasyon seviyesi
REPEATABLEREAD REPEATABLE READ izolasyon seviyesi
SERIALIZABLE SERIALIZABLE izolasyon seviyesi
SNAPSHOT SNAPSHOT izolasyon seviyesi
UPDLOCK Güncelleştirme kilitler
XLOCK Özel kilit
READPAST Kilitli satırları atlar
READCOMMITTEDLOCK READ COMMITTED LOCK izolasyon seviyesi

Kurulum

NuGet Paketi

dotnet add package MCDLabs.Utility.SqlHelper.TableHint

veya Package Manager Console:

Install-Package MCDLabs.Utility.SqlHelper.TableHint

Hızlı Başlangıç

1. DbContext Yapılandırması

DbContext'inizi yapılandırırken interceptor'u ekleyin:

using MCD.EFCore.TableHint.Extensions;

var optionsBuilder = new DbContextOptionsBuilder<YourDbContext>();
optionsBuilder
    .UseSqlServer(connectionString)
    .UseNoLockInterceptor();  // Interceptor'u ekleyin

var context = new YourDbContext(optionsBuilder.Options);

2. LINQ Sorgularında Hint Uygulama

Tüm Tablolara Otomatik Hint Uygulama

applyToAllEntities: true parametresi kullanarak DbContext'teki TÜM entity türlerine otomatik olarak hint uygulayabilirsiniz:

// DbContext'teki tüm tablolara NOLOCK hint'ini otomatik uygula
var users = dbContext.Users
    .WithHint(dbContext, SqlServerTableHintFlags.NOLOCK, applyToAllEntities: true)
    .Where(u => u.IsActive)
    .ToList();

// Kısa syntax (applyToAllEntities parametresi olarak true geçir)
var orders = dbContext.Orders
    .WithHint(dbContext, SqlServerTableHintFlags.NOLOCK, true)
    .Where(o => o.TotalAmount > 100)
    .ToList();

Avantajları:

  • Manuel olarak her tablo için typeof() belirtmek zorunda değilsiniz
  • DbContext'teki tüm tabloları otomatik olarak kapsar
  • Include edilen related entities'ler de hint'i alır
Temel Kullanım (Tek Tablo)
var users = dbContext.Users
    .WithHint(dbContext, SqlServerTableHintFlags.NOLOCK)
    .Where(u => u.IsActive)
    .ToList();
Birden Fazla Hint Kombinasyonu
var users = dbContext.Users
    .WithHint(dbContext, 
        SqlServerTableHintFlags.NOLOCK | SqlServerTableHintFlags.ROWLOCK)
    .Where(u => u.Age > 18)
    .ToList();
Belirli Tip İçin Hint Uygulama
// Sadece User tablosu için NOLOCK uygula
var result = dbContext.Users
    .WithHint(dbContext, SqlServerTableHintFlags.NOLOCK, typeof(User))
    .Include(u => u.Orders)
    .ToList();
Birden Fazla Tablo İçin Hint Uygulama
// Hem User hem de Order tabloları için NOLOCK uygula
var result = dbContext.Users
    .WithHint(dbContext, SqlServerTableHintFlags.NOLOCK, 
        typeof(User), typeof(Order))
    .Include(u => u.Orders)
    .ToList();

3. Async Sorgular

var users = await dbContext.Users
    .WithHint(dbContext, SqlServerTableHintFlags.NOLOCK)
    .Where(u => u.IsActive)
    .ToListAsync();

Mimarı

Temel Bileşenler

1. BaseQueryHookAction (Abstractions/BaseQueryHookAction.cs)

Tüm hook eylemlerinin temel sınıfı. Hint bilgilerini yönetir.

public abstract class BaseQueryHookAction
{
    public abstract string GetKey();
    public abstract bool IsOf(Type type);
}
2. TableHintBuilder (Abstractions/TableHintBuilder.cs)

Table hint'leri tanımlamak için temel builder sınıfı.

public abstract class TableHintBuilder : BaseQueryHookAction
{
    public string Hint { get; set; }
    public SqlServerTableHintFlags SqlServerTableHint { get; set; }
}
3. QueryHookCommandInterceptor (Infrastructure/Interceptor/QueryHookCommandInterceptor.cs)

EF Core komut interceptor'u. SQL komutlarını değiştirir ve hint'leri enjekte eder.

Temel Görevleri:

  • SQL komutlarını yakalar
  • Hint bilgilerini çıkarır
  • Target table adlarını belirler
  • SQL'e table hints ekler
4. QueryHookManager (Infrastructure/QueryHookManager.cs)

Hook eylemlerini yönetir ve Cache'ler.

public static class QueryHookManager
{
    public static IQueryable<T> Hook<T>(
        IQueryable<T> query, 
        DbContext context, 
        BaseQueryHookAction hookAction)
}
5. WithHintExtensions (Infrastructure/WithHintExtensions.cs)

LINQ sorguları üzerine WithHint() extension method'u sağlar.

public static class WithHintExtensions
{
    public static IQueryable<T> WithHint<T>(
        this IQueryable<T> source, 
        DbContext context, 
        SqlServerTableHintFlags hint, 
        params Type[] types)
}

İş Akışı

LINQ Query
    ↓
WithHint() Extension Method çağrılır
    ↓
Hook Action (TableHintBuilder<T>) oluşturulur
    ↓
QueryHookManager.Hook() - Hint Cache'e eklenir
    ↓
Query TagWith() ile işaretlenir (MCD_EFCORE: prefix ile)
    ↓
Sorgu Çalıştırılır
    ↓
QueryHookCommandInterceptor.ReaderExecuting() tetiklenir
    ↓
SQL Komutundan Tag Çıkarılır
    ↓
Target Tablo Adları Belirlenir
    ↓
Table Hints SQL'e Eklenir
    ↓
Değiştirilmiş SQL Komut Çalıştırılır
    ↓
Sonuçlar Döndürülür

İleri Seviye Kullanım

Özel Hint Mesajları

// Özel hint mesajı ile sorgu
var users = dbContext.Users
    .Where(u => u.Department == "Sales")
    .ToList();

// SQL'de görülecek hint:
// FROM [Users] WITH (NOLOCK, ROWLOCK)

Join Sorguları

var result = (from u in dbContext.Users.WithHint(dbContext, SqlServerTableHintFlags.NOLOCK)
              join o in dbContext.Orders.WithHint(dbContext, SqlServerTableHintFlags.NOLOCK) 
                on u.Id equals o.UserId
              select new { u.Name, o.OrderDate })
    .ToList();

Include ile Birlikte Kullanım

var users = dbContext.Users
    .WithHint(dbContext, SqlServerTableHintFlags.NOLOCK, typeof(User), typeof(Order))
    .Include(u => u.Orders)
    .Include(u => u.Addresses)
    .ToList();

Önemli Notlar ⚠️

InMemory Provider Uyarısı

Bu kütüphane sadece gerçek veritabanı sağlayıcıları (SQL Server, PostgreSQL, MySQL vb.) ile çalışır. InMemory provider kullanıyorsanız aşağıdaki hata alırsınız:

NotSupportedException: EFCore InMemory provider, interceptor 
gerektiren query hook uzantılarını desteklemez.

Çözüm: Unit test'lerinizde InMemory provider yerine Testcontainers veya test veritabanı kullanın.

Weak Reference Caching

Kütüphane ConditionalWeakTable kullanarak DbContext örneklerine bağlı hint cache'i tutar. DbContext serbest bırakıldığında, otomatik olarak garbage collection'a gider.

Kilit Seviyeleri

Hint uygulanırken dikkatli olun:

  • NOLOCK: Performans en yüksek ama "Dirty Read" riski var
  • TABLOCK: Tüm tabloyu kilitler, diğer sorgular bekler
  • FORCESEEK/FORCESCAN: Sorgu planlayıcısı seçimini override eder

Örnek Senaryolar

Senaryo 1: Yoğun Okuma Işlemleri

public async Task<IEnumerable<UserDto>> GetActiveUsersAsync()
{
    return await dbContext.Users
        .WithHint(dbContext, SqlServerTableHintFlags.NOLOCK)
        .Where(u => u.IsActive)
        .Select(u => new UserDto 
        { 
            Id = u.Id, 
            Name = u.Name, 
            Email = u.Email 
        })
        .ToListAsync();
}

Senaryo 2: Raporlama Sorguları

public async Task<SalesReport> GetSalesReportAsync(DateTime startDate)
{
    var sales = await dbContext.Orders
        .WithHint(dbContext, SqlServerTableHintFlags.FORCESEEK)
        .Where(o => o.CreatedDate >= startDate)
        .GroupBy(o => o.SalesPersonId)
        .Select(g => new { 
            SalesPersonId = g.Key, 
            TotalAmount = g.Sum(o => o.Amount) 
        })
        .ToListAsync();

    return new SalesReport { Sales = sales };
}

Senaryo 3: Belirli Kilit Stratejisi

public async Task<bool> TransferFundsAsync(int fromAccountId, int toAccountId, decimal amount)
{
    using var transaction = await dbContext.Database.BeginTransactionAsync();
    try
    {
        // Hesapları UPDLOCK ile kilitler
        var fromAccount = await dbContext.Accounts
            .WithHint(dbContext, SqlServerTableHintFlags.UPDLOCK)
            .FirstOrDefaultAsync(a => a.Id == fromAccountId);

        var toAccount = await dbContext.Accounts
            .WithHint(dbContext, SqlServerTableHintFlags.UPDLOCK)
            .FirstOrDefaultAsync(a => a.Id == toAccountId);

        fromAccount.Balance -= amount;
        toAccount.Balance += amount;

        await dbContext.SaveChangesAsync();
        await transaction.CommitAsync();
        return true;
    }
    catch
    {
        await transaction.RollbackAsync();
        return false;
    }
}

Sorun Giderme

Problem: "DbContext not found" hatası

Çözüm: WithHint() çağrısında DbContext örneğini doğru şekilde geçirdiğinizden emin olun:

// ❌ Yanlış
var users = dbContext.Users.WithHint(null, SqlServerTableHintFlags.NOLOCK);

// ✅ Doğru
var users = dbContext.Users.WithHint(dbContext, SqlServerTableHintFlags.NOLOCK);

Problem: Hint SQL'de görünmüyor

Çözüm:

  1. Interceptor'un DbContext yapılandırmasında kayıtlı olduğundan emin olun
  2. SQL Server profiler ile gerçek SQL komutunu kontrol edin
  3. InMemory provider kullanmadığınızdan emin olun

Problem: "NotSupportedException" hatası

Çözüm: InMemory provider kullanıyorsanız, gerçek bir SQL Server veritabanı bağlantısı kullanın.

Performans İpuçları

  1. NOLOCK Kullanın: Salt okunur sorgularda NOLOCK kullanarak performansı artırın
  2. FORCESEEK/FORCESCAN: Sorgu planlayıcısı suboptimal seçim yapıyorsa kullanın
  3. Uygun Kilit Seviyeleri: ROWLOCK ve PAGLOCK tablo kilitleri yerine tercih edin
  4. Endeks Stratejisi: Hint'ler endeks stratejisini tamamlar, endeksleri optimize edin

Gereksinimler

  • .NET Runtime: .NET 9.0 veya daha yeni
  • Entity Framework Core: 9.0.8 veya daha yeni
  • Veritabanı: SQL Server 2016 veya daha yeni

Versiyon Tarihi

Versiyon Tarih Değişiklikler
1.0.2 2026-05-17 Başlangıç sürümü
1.0.1 - -
1.0.0 - -

Lisans

Bu proje MIT Lisansı altında lisanslanmıştır. Ayrıntılar için LICENSE dosyasına bakın.

Yazar

Mert Can Düldül

Katkılar

Katkılar açıktır! Lütfen pull request gönderin veya issue açın.

İletişim & Destek

Kaynaklar


Sürüm: 1.0.2
Son Güncelleme: 17 Mayıs 2026

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.3 116 5/17/2026
1.0.2 104 5/17/2026
1.0.0 2,265 11/18/2025