Domanda

Sto usando il modello di visitatore standard per scorrere un albero delle espressioni LINQ al fine di generare clausole WHERE SQL dinamiche.

Il mio problema è che, diversamente da C #, non puoi usare un'espressione booleana autonoma in SQL; devi confrontarlo con 1 o 0.

Data questa ipotetica espressione lambda:

h => h.Enabled || h.Enabled == false

Sarebbe facile generare erroneamente questo codice:

WHERE Enabled OR Enabled = 0

o questo codice:

WHERE (Enabled = 1) OR (Enabled = 1) = 0

Entrambi ovviamente genereranno un errore SQL. Quale logica dovrei applicare per aggirare questo senza che il mio codice inizi a sembrare davvero ottuso mentre mi immergo nelle sottotitoli per capire quale potrebbe essere il caso?

EDIT: l'esempio sopra è ovviamente ridondante - lo sto usando solo per illustrare un punto.

Esempi che potrebbero creare questo scenario:

h => h.Enabled
h => h.Enabled == enabled
h => h.Enabled == true

Naturalmente, l'ultimo esempio è uno stile scadente, ma il mio codice è stato progettato per funzionare indipendentemente dal livello di abilità del programmatore, quindi non soddisfare scenari ridondanti sarebbe una forma scadente da parte mia.

È stato utile?

Soluzione

I seguenti casi sono piuttosto semplici:

h => h.Enabled == enabled
h => h.Enabled == true

Questi sono nodi BinaryExpression e puoi tradurli direttamente in:

WHERE (Enabled = @p0)
WHERE (Enabled = 1)

I casi speciali che è necessario gestire sono:

h => h.Enabled
h => !h.Enabled

Questi sono rappresentati diversamente nell'albero delle espressioni (come MemberExpression ). Pertanto, dovrai specificare il MemberExpression e stabilire se sta accedendo a una proprietà booleana o meno. In tal caso, lo traduci nella forma canonica (rilevando il UnaryExpression nel secondo esempio):

WHERE (Enabled = 1)
WHERE (Enabled = 0)

In alternativa, potresti essere in grado di pre-elaborare l'albero delle espressioni e tradurre eventuali casi speciali nella loro forma canonica (albero delle espressioni). Ad esempio, tutti i nodi MemberExpression che soddisfano i criteri potrebbero essere trasformati nel BinaryExpression corretto.

Altri suggerimenti

Non è possibile elaborare completamente gli operandi prima di sviluppare gli operatori?

Ie. Valuta ciascuno di:

h => h.Enabled
h => h.Enabled == enabled
h => h.Enabled == true

a

WHERE (Enabled = 1)

e quindi nel caso in cui gli operatori siano inclusi nella lambda, elabora la raccolta di operandi renderizzati con SQL equivalente per soddisfare i requisiti degli operatori.

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