Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Thêm gợi ý truy vấn khi gọi Hàm Table-Valued

Tôi đã xem qua điều này:

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

Và có vẻ như bạn có thể làm điều gì đó như sau:

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);
    }
}

Và đăng ký nó như thế này (Tôi đã làm điều đó trong Application_Start trong tổng số global.asax.cs ):

DbInterception.Add(new HintInterceptor());

Và nó sẽ cho phép bạn thay đổi CommandText . Vấn đề duy nhất là bây giờ nó được đính kèm cho mọi truy vấn của người đọc có thể là một vấn đề vì một số trong số họ có thể bị ảnh hưởng tiêu cực bởi gợi ý đó. Tôi đoán mình có thể làm gì đó với ngữ cảnh để tìm ra gợi ý có phù hợp hay không, hoặc trường hợp tệ hơn tôi có thể kiểm tra CommandText chính nó.

Có vẻ như đây không phải là giải pháp thanh lịch hoặc chi tiết nhất.

Chỉnh sửa :Từ interceptorContext , bạn có thể lấy DbContexts , vì vậy tôi đã xác định một giao diện trông giống như sau:

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

Và sau đó tạo một lớp dẫn xuất từ ​​DbContext ban đầu của tôi (được tạo bởi EF) và triển khai giao diện trên. Sau đó, tôi đã thay đổi thiết bị đánh chặn của mình trông như thế này:

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);
    }
}

Bây giờ để sử dụng nó, tôi tạo một ngữ cảnh bằng cách sử dụng lớp dẫn xuất của mình thay vì lớp gốc, đặt QueryHint thành bất cứ thứ gì tôi muốn (recompile trong trường hợp này) và đặt ApplyHint ngay trước khi tôi thực hiện lệnh và đặt nó trở lại false sau đó.

Để làm cho tất cả điều này trở nên khép kín hơn một chút, tôi đã kết thúc việc xác định một giao diện như sau:

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

Và mở rộng ngữ cảnh db của tôi như thế này (tất nhiên, bạn có thể chỉ sử dụng một lớp một phần để mở rộng lớp được tạo bởi EF):

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

Và sau đó, để làm cho phần bật, tắt dễ xử lý hơn một chút, tôi đã xác định điều này:

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;
    }
}

Bây giờ để sử dụng nó, tôi chỉ có thể làm điều này:

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
}

Điều này có thể hơi quá mức cần thiết và có thể được phát triển thêm (ví dụ:sử dụng enum cho các gợi ý có sẵn thay vì một chuỗi - hoặc phân lớp một recompile gợi ý truy vấn để bạn không cần chỉ định chuỗi recompile mọi lúc và có nguy cơ mắc lỗi đánh máy), nhưng nó đã giải quyết được vấn đề trước mắt của tôi.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm cách nào để xem toàn bộ nội dung của cột văn bản hoặc varchar (MAX) trong SQL Server 2008 Management Studio?

  2. Đánh giá phần mềm - Stellar Repair cho MS SQL

  3. SQL Server là gì? (Định nghĩa, Phiên bản, Phiên bản)

  4. Tầng một ngày trong máy chủ SQL

  5. Sự khác biệt về hiệu suất chính giữa kiểu dữ liệu SQL Server varchar và nvarchar là gì?