sql >> Databáze >  >> RDS >> Sqlserver

Přidání nápovědy k dotazu při volání funkce Table-Valued Function

Narazil jsem na toto:

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

A zdá se, že můžete udělat něco takového:

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

A zaregistrujte to takto (udělal jsem to v Application_Start z global.asax.cs ):

DbInterception.Add(new HintInterceptor());

A umožní vám to změnit CommandText . Jediný problém je, že je nyní připojen pro každý dotaz čtenáře, což může být problém, protože některé z nich mohou být touto nápovědou negativně ovlivněny. Hádám, že mohu něco udělat s kontextem, abych zjistil, zda je nápověda vhodná nebo ne, nebo v horším případě bych mohl prozkoumat CommandText sám.

Nezdá se to úplně nejelegantnější nebo nejjemnější řešení.

Upravit :Z interceptorContext , můžete získat DbContexts , takže jsem definoval rozhraní, které vypadá takto:

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

A pak vytvořil třídu, která pochází z mého původního DbContextu (vygenerovaného EF) a implementuje výše uvedené rozhraní. Pak jsem změnil svůj interceptor, aby vypadal takto:

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

Nyní, abych to mohl použít, vytvořím kontext pomocí své odvozené třídy namísto původní, nastavte QueryHint na cokoliv, co chci, aby to bylo (recompile v tomto případě) a nastavte ApplyHint těsně před provedením příkazu a poté jej nastavím zpět na hodnotu false.

Aby to všechno bylo trochu více soběstačné, nakonec jsem definoval rozhraní jako toto:

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

A rozšířil můj kontext db takto (můžete samozřejmě použít jen částečnou třídu k rozšíření třídy vygenerované EF):

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

A pak, aby byla manipulace se zapínací a vypínací částí trochu jednodušší, definoval jsem toto:

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

Abych to teď mohl použít, mohu udělat jen toto:

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
}

To může být trochu přehnané a mohlo by být dále rozvíjeno (například použitím výčtu pro dostupné rady místo řetězce - nebo podtřídou recompile dotaz, takže nemusíte zadávat řetězec recompile pokaždé a riskuji překlep), ale můj okamžitý problém to vyřešilo.



  1. Spouštěč MySQL při událostech vložení/aktualizace

  2. Tipy pro poskytování výkonu databáze MySQL – část druhá

  3. MySQL Objednávka před Seskupit podle

  4. Jak mohu simulovat proměnnou pole v MySQL?