sql >> Database teknologi >  >> RDS >> Sqlserver

Tilføjelse af et forespørgselstip, når du kalder Table-Valued Function

Jeg stødte på dette:

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

Og det ser ud til, at du kan gøre noget som dette:

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

Og registrer det sådan her (jeg gjorde det i Application_Start af global.asax.cs ):

DbInterception.Add(new HintInterceptor());

Og det vil lade dig ændre CommandText . Det eneste problem er, at det nu er vedhæftet til hver læserforespørgsel, som kan være et problem, da nogle af dem kan blive negativt påvirket af dette tip. Jeg gætter på, at jeg kan gøre noget med konteksten for at finde ud af, om hintet er passende eller ej, eller i værre tilfælde kunne jeg undersøge CommandText sig selv.

Virker ikke helt den mest elegante eller finkornede løsning.

Rediger :Fra interceptorContext , kan du få DbContexts , så jeg definerede en grænseflade, der ser sådan ud:

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

Og så oprettede en klasse, der stammer fra min originale DbContext (genereret af EF) og implementerer ovenstående grænseflade. Så ændrede jeg min interceptor til at se sådan ud:

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

For nu at bruge det, opretter jeg en kontekst ved hjælp af min afledte klasse i stedet for originalen, sæt QueryHint til hvad jeg vil have det til at være (recompile i dette tilfælde) og indstil ApplyHint lige før jeg udfører kommandoen og sætter den tilbage til falsk bagefter.

For at gøre det hele lidt mere selvstændigt, endte jeg med at definere en grænseflade som denne:

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

Og udvidede min db-kontekst sådan her (du kunne selvfølgelig bare bruge en delvis klasse til også at udvide den EF-genererede klasse):

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

Og så, for at gøre tænd- og sluk-delen lidt nemmere at håndtere, definerede jeg dette:

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

For nu at bruge det, kan jeg gøre netop dette:

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
}

Dette er måske lidt overdrevet og kunne udvikles yderligere (for eksempel ved at bruge en enum for tilgængelige tip i stedet for en streng - eller underklasser en recompile forespørgselstip, så du ikke behøver at angive strengen recompile hver gang og risikere en tastefejl), men det løste mit umiddelbare problem.



  1. Implementer MySQL relationelle databaser på Ubuntu 12.04 (præcis Pangolin)

  2. org.hibernate.internal.util.config.ConfigurationException:Kunne ikke finde cfg.xml ressource [/HibernateTest/src/hibernate.cfg.xml]

  3. MySQL MariaDB – Forespørgsel ved hjælp af Temp-tabel

  4. Konverter 'tid' til 'smalldatetime' i SQL Server (T-SQL-eksempler)