Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Dodawanie wskazówki do zapytania podczas wywoływania funkcji z wartościami tabelowymi

Natknąłem się na to:

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

I wygląda na to, że możesz zrobić coś takiego:

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

I zarejestruj to w ten sposób (zrobiłem to w Application_Start z global.asax.cs ):

DbInterception.Add(new HintInterceptor());

I pozwoli ci zmienić CommandText . Jedynym problemem jest to, że jest teraz dołączony do każdego zapytanie czytelnika, które może być problemem, ponieważ niektóre z nich mogą mieć negatywny wpływ na tę wskazówkę. Zgaduję, że mogę coś zrobić z kontekstem, aby dowiedzieć się, czy podpowiedź jest odpowiednia, czy nie, lub, co gorsza, mógłbym sprawdzić CommandText się.

Nie wydaje się najbardziej eleganckim lub drobnoziarnistym rozwiązaniem.

Edytuj :Z interceptorContext , możesz pobrać DbContexts , więc zdefiniowałem interfejs, który wygląda tak:

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

A następnie utworzyłem klasę, która wywodzi się z mojego oryginalnego DbContext (wygenerowanego przez EF) i implementuje powyższy interfejs. Następnie zmieniłem myśliwiec tak, aby wyglądał tak:

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

Teraz, aby go użyć, tworzę kontekst przy użyciu mojej klasy pochodnej zamiast oryginalnej, ustawiam QueryHint do czegokolwiek zechcę (recompile w tym przypadku) i ustaw ApplyHint tuż przed wykonaniem polecenia, a potem ustawiam je z powrotem na false.

Aby wszystko było bardziej samowystarczalne, zdefiniowałem interfejs w następujący sposób:

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

I rozszerzyłem mój kontekst bazy danych w ten sposób (oczywiście można po prostu użyć częściowej klasy do rozszerzenia klasy generowanej przez EF):

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

A potem, aby nieco ułatwić obsługę części włączania i wyłączania, zdefiniowałem to:

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

Teraz, aby z niego skorzystać, mogę zrobić tylko to:

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
}

Może to być trochę przesadne i może być dalej rozwijane (na przykład używając wyliczenia dla dostępnych wskazówek zamiast ciągu znaków - lub podklasy recompile wskazówka zapytania, dzięki czemu nie trzeba określać ciągu recompile za każdym razem i ryzykować literówkę), ale rozwiązało to mój najpilniejszy problem.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Wykluczyć kolumnę za pomocą SELECT * [oprócz kolumny A] FROM tabela A?

  2. Audyt danych w NHibernate i SqlServer

  3. Czy integracja SQL Server CLR obsługuje pliki konfiguracyjne?

  4. Skonfiguruj Lucene.Net z SQL Server

  5. 3 sposoby na uzyskanie nazwy dnia z daty w SQL Server (T-SQL)