Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Menambahkan petunjuk kueri saat memanggil Fungsi Bernilai Tabel

Saya menemukan ini:

https://entityframework.codeplex.com/wikipage?title=Interception

Dan tampaknya Anda dapat melakukan sesuatu seperti ini:

public class HintInterceptor : DbCommandInterceptor
{
    public override void ReaderExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<System.Data.Common.DbDataReader> interceptionContext)
    {
        command.CommandText += " option (recompile)";
        base.ReaderExecuting(command, interceptionContext);
    }
}

Dan daftarkan seperti ini (saya melakukannya di Application_Start dari global.asax.cs ):

DbInterception.Add(new HintInterceptor());

Dan itu akan membiarkan Anda mengubah CommandText . Satu-satunya masalah adalah sekarang dilampirkan untuk setiap permintaan pembaca yang mungkin menjadi masalah karena beberapa dari mereka mungkin terkena dampak negatif oleh petunjuk itu. Saya kira saya bisa melakukan sesuatu dengan konteksnya untuk mencari tahu apakah petunjuknya sesuai atau tidak, atau lebih buruk lagi saya bisa memeriksa CommandText sendiri.

Tampaknya bukan solusi yang paling elegan atau halus.

Sunting :Dari interceptorContext , Anda bisa mendapatkan DbContexts , jadi saya mendefinisikan antarmuka yang terlihat seperti ini:

public interface IQueryHintContext
{
    string QueryHint { get; set; }
    bool ApplyHint { get; set; }
}

Dan kemudian membuat kelas yang berasal dari DbContext asli saya (dihasilkan oleh EF) dan mengimplementasikan antarmuka di atas. Kemudian saya mengubah pencegat saya menjadi seperti ini:

public class HintInterceptor : DbCommandInterceptor
{
    public override void ReaderExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<System.Data.Common.DbDataReader> interceptionContext)
    {
        if (interceptionContext.DbContexts.Any(db => db is Dal.IQueryHintContext))
        {
            var ctx = interceptionContext.DbContexts.First(db => db is Dal.IQueryHintContext) as Dal.IQueryHintContext;
            if (ctx.ApplyHint)
            {
                command.CommandText += string.Format(" option ({0})", ctx.QueryHint);
            }
        }
        base.ReaderExecuting(command, interceptionContext);
    }
}

Sekarang untuk menggunakannya, saya membuat konteks menggunakan kelas turunan saya alih-alih yang asli, atur QueryHint untuk apa pun yang saya inginkan (recompile dalam hal ini) dan atur ApplyHint tepat sebelum saya menjalankan perintah dan mengembalikannya ke false setelahnya.

Untuk membuat semua ini sedikit lebih mandiri, saya akhirnya mendefinisikan antarmuka seperti ini:

public interface IQueryHintContext
{
    string QueryHint { get; set; }
    bool ApplyHint { get; set; }
}

Dan memperluas konteks db saya seperti ini (Anda tentu saja dapat menggunakan kelas parsial untuk memperluas kelas yang dihasilkan EF juga):

public class MyEntities_Ext : MyEntities, IQueryHintContext
{
    public string QueryHint { get; set; }
    public bool ApplyHint { get; set; }
}

Dan kemudian, untuk membuat bagian pengaktifan dan penonaktifan sedikit lebih mudah ditangani, saya mendefinisikan ini:

public class HintScope : IDisposable
{
    public IQueryHintContext Context { get; private set; }
    public void Dispose()
    {
        Context.ApplyHint = false;
    }

    public HintScope(IQueryHintContext context, string hint)
    {
        Context = context;
        Context.ApplyHint = true;
        Context.QueryHint = hint;
    }
}

Sekarang untuk menggunakannya, saya bisa melakukan ini:

using (var ctx = new MyEntities_Ext()) 
{
    // any code that didn't need the query hint
    // ....
    // Now we want the query hint
    using (var qh = new HintScope(ctx, "recompile"))
    {
        // query that needs the recompile hint
    }
    // back to non-hint code
}

Ini mungkin sedikit berlebihan dan dapat dikembangkan lebih lanjut (misalnya, menggunakan enum untuk petunjuk yang tersedia alih-alih string - atau mensubklasifikasikan recompile petunjuk kueri sehingga Anda tidak perlu menentukan string recompile setiap kali dan berisiko salah ketik), tetapi itu memecahkan masalah langsung saya.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Apa pentingnya 1/1/1753 di SQL Server?

  2. Menggunakan ROLLBACK Transaksi di SQL Server

  3. Pernyataan SQL GROUP BY CASE dengan fungsi agregat

  4. Cara menggabungkan teks dari beberapa baris menjadi satu string teks di SQL Server

  5. Apa itu SQL Server?