sql >> Database >  >> RDS >> Sqlserver

Een vraaghint toevoegen bij het aanroepen van Table-Valued Function

Ik kwam dit tegen:

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

En het lijkt erop dat je zoiets als dit kunt doen:

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

En registreer het als volgt (ik deed het in Application_Start van global.asax.cs ):

DbInterception.Add(new HintInterceptor());

En je kunt de CommandText . wijzigen . Het enige probleem is dat het nu is bijgevoegd voor elke lezerquery, wat een probleem kan zijn, omdat sommige van hen negatief kunnen worden beïnvloed door die hint. Ik vermoed dat ik iets met de context kan doen om erachter te komen of de hint gepast is of niet, of in het ergste geval zou ik de CommandText kunnen onderzoeken zelf.

Lijkt niet echt de meest elegante of fijnmazige oplossing.

Bewerken :Van de interceptorContext , kunt u de DbContexts , dus ik heb een interface gedefinieerd die er als volgt uitziet:

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

En vervolgens een klasse gemaakt die is afgeleid van mijn originele DbContext (gegenereerd door EF) en de bovenstaande interface implementeert. Toen veranderde ik mijn interceptor om er zo uit te zien:

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

Om het nu te gebruiken, maak ik een context met behulp van mijn afgeleide klasse in plaats van de originele, set QueryHint naar wat ik maar wil (recompile in dit geval) en stel ApplyHint in vlak voordat ik het commando uitvoer en het daarna weer op false zet.

Om dit allemaal een beetje meer op zichzelf staand te maken, heb ik uiteindelijk een interface als volgt gedefinieerd:

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

En breidde mijn db-context op deze manier uit (je zou natuurlijk ook een gedeeltelijke klasse kunnen gebruiken om de door EF gegenereerde klasse uit te breiden):

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

En om het in- en uitschakelen een beetje gemakkelijker te maken, heb ik dit gedefinieerd:

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

Om het nu te gebruiken, kan ik precies dit doen:

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
}

Dit is misschien een beetje overdreven en zou verder kunnen worden ontwikkeld (bijvoorbeeld een opsomming gebruiken voor beschikbare hints in plaats van een tekenreeks - of een recompile subclasseren vraaghint zodat u de tekenreeks recompile niet hoeft op te geven elke keer en riskeer een typfout), maar het loste mijn onmiddellijke probleem op.



  1. ScaleGrid DBaaS breidt MySQL-hostingservices uit via AWS Cloud

  2. Hoe duplicaten te verwijderen uit een door komma's gescheiden lijst op regex in Oracle, maar ik wil geen dubbele waarden?

  3. Kardinaliteitsschatting voor meerdere predikaten

  4. Jenkins gebruiken met Kubernetes AWS, deel 3