Domanda

Sto cercando di fare qualcosa che sembra molto semplice ma ho colpito enormi difficoltà quando voglio renderlo più dinamico.

    Expression<Func<TableServiceEntity, bool>> predicate = (e) => e.PartitionKey == "model" && (e.RowKey == "home" || e.RowKey == "shared");

context.CreateQuery<TableServiceEntity>(tableName).Where(predicate);
.

Vorrei passare una matrice di RowKey invece di dover codice duro il predicato.

Quando provo a costruire un albero di espressione, ricevo un'eccezione non supportata, penso che non supporti il richiamo come parte dell'albero di espressione.

qualcuno sa come costruire ed esprimere l'albero esattamente come il predicato per evitare l'eccezione non supportata?

Grazie per anticipo

È stato utile?

Soluzione

Quindi, puoi costruire la query in modo dinamico usando qualcosa come questo (preso da PhluforyFotos Sample): .

        Expression<Func<PhotoTagRow, bool>> search = null;
        foreach (var tag in tags)
        {
            var id = tag.Trim().ToLowerInvariant();

            if (String.IsNullOrEmpty(id))
            {
                continue;
            }

            Expression<Func<PhotoTagRow, bool>> addendum = t => t.PartitionKey == id;

            if (search == null)
            {
                search = addendum;
            }
            else
            {
                search = Expression.Lambda<Func<PhotoTagRow, bool>>(Expression.OrElse(search.Body, addendum.Body), search.Parameters);
            }
        }
.

Ora, una volta che hai "cerca" puoi semplicemente passare come il predicato nella tua clausola dove.

comunque , voglio convincerti a non farlo. Sto rispondendo alla tua domanda, ma ti sto dicendo che è una cattiva idea fare un multiplo '|' O clausola nella deposito della tabella. Il motivo è che oggi almeno, queste query non possono essere ottimizzate e causano una scansione da tavolo completa. Le prestazioni saranno orrendi con qualsiasi quantità non banale di dati. Inoltre, se costruisci i tuoi predischi in modo dinamico come questo gestisci il rischio di soffiare il limite dell'URL (tenerlo in mente).

Questo codice in PhluforyFotos mostra come, ma in realtà è una cattiva pratica (lo so, l'ho scritto). Dovrebbe davvero essere ottimizzato per eseguire ciascuna o clausola separatamente in parallelo. È così che dovresti davvero farlo. E le clausole sono ok, ma o le clausole dovrebbero essere parallelite (usa Plinq o TPL) e dovresti aggregare i risultati. Sarà molto più veloce.

hth.

Altri suggerimenti

Credo che HTH ha detto di questo tipo di query che fa una scansione completa della tabella non è corretta dalla documentazione che ho letto.Azure eseguirà una scansione di partizione piuttosto che una scansione da tavolo che è una grande differenza nelle prestazioni.

Ecco la mia soluzione Si prega di leggere anche la risposta da Hth che ha sottolineato che questa non è una migliore pratica.

var parameter = Expression.Parameter(typeof(TableServiceEntity), "e");

var getPartitionKey = typeof(TableServiceEntity).GetProperty("PartitionKey").GetGetMethod();
var getRowKey = typeof(TableServiceEntity).GetProperty("RowKey").GetGetMethod();

var getPartition = Expression.Property(parameter, getPartitionKey);
var getRow = Expression.Property(parameter, getRowKey);

var constPartition = Expression.Constant("model", typeof(string));
var constRow1 = Expression.Constant("home", typeof(string));
var constRow2 = Expression.Constant("shared", typeof(string));

var equalPartition = Expression.Equal(getPartition, constPartition);
var equalRow1 = Expression.Equal(getRow, constRow1);
var equalRow2 = Expression.Equal(getRow, constRow2);

var and = Expression.AndAlso(equalPartition, Expression.OrElse(equalRow1, equalRow2));

return Expression.Lambda<Func<TableServiceEntity, bool>>(and, parameter);
.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top