Personalizzazione di SQL con le estensioni di Dapper




 Sto usando le estensioni di Dapper per alcuni dei miei tipi e funziona davvero bene per la maggior parte dei casi d'uso. Mi sono imbattuto in un caso in cui ho una relazione molti-molti, e voglio fare qualcosa come: - 


```
SELECT id,a,b,c FROM Foo WHERE Foo.id in (SELECT foo_id FROM foo-bar WHERE bar-id=@bar_id)

```
 Ovviamente Dapper Extensions può gestire "SELECT id, a, b, c FROM Foo" ma non la seconda parte. Potrei fare una selezione per ottenere la lista di Foo id che voglio, e poi passarla a Dapper Extensions ma è meno efficiente. 

 La parte che non posso fare con Plain Dapper è ottenere automaticamente la lista di colonne SELECT, quindi quello che mi piacerebbe davvero è un modo per: 

* Ottieni l'elenco di colonne SELECT dai meccanismi interni di Dapper Extension
* Ottieni la base "SELEZIONA id, a, b, c FROM Foo" dai meccanismi interni di Dapper Extension
* Hook Dapper Extensions Ottieni il codice in modo che io possa aggiungere una clausola WHERE personalizzata

 Ho esaminato il codice, ma non riesco a capire come fare nessuna di queste cose. Qualcuno può aiutare? Ho lavorato con Dapper e "SELECT * ..." al momento, ma sono sicuro che c'è un modo migliore.
Non sapevo che questo non fosse supportato nel 2012. Quindi circa 1,7K visualizzazioni in due anni e non molta esposizione. Ma nel caso qualcuno di nuovo a Dapper sia atterrato qui e chiedendosi se funziona, la risposta è che funziona. Utilizzando l'ultima versione di, al momento della stesura di questo documento, [Dapper v1.42 di nuget](https://www.nuget.org/packages/Dapper/) : 


```
var sql = "SELECT id,a,b,c FROM Foo WHERE Foo.id in (
    SELECT foo_id FROM foo-bar WHERE bar-id=@bar_id)"
using (var cn = new SqlConnection(the_connection_string)) {
  cn.Open();
  var returnedObject = cn.Query<dynamic>(sql, new { bar_id = some_value });
}

```
Non sono sicuro se il suo buon approccio per risolverlo, ma ha funzionato per me. 

 Ho appena inserito in quel tavolo la versione corretta e i nomi delle migrazioni già applicate, l'ho fatto in EF Core e funziona davvero, ma per favore aspetta qualcuno che si accorga di ciò che sto scrivendo. 

 Il problema che vedo è che hai bisogno di riempire altri due campi (in EF Core ci sono solo due colonne) ma penso che puoi riceverli usando per esempio SQL Profiler FYI per chiunque altro .... 

 bcp "Seleziona qualsiasi cosa da dbInstanceName.dbo.tableName" quesryout C: \ output.txt -e C: \ errors.txt -c -T -S localhost \ dbName L'albero delle espressioni è così potente perché ti consente di trattare il **codice** come **dati** . Gli utenti sono abituati a creare dati, salvarli e tornare in seguito. 

 Gli alberi delle espressioni ti consentono di fare la stessa cosa con il codice. Ad esempio, puoi inserire l'input dell'utente (caselle di controllo, intervalli numerici, ecc.) E tradurlo in un albero di espressioni. Quell'albero di espressioni può quindi essere eseguito o memorizzato per un uso successivo. Molto bello 

 Pensa agli usi pratici relativi alla creazione di rapporti come la creazione e il salvataggio di filtri dati e mappature dei dati. Un altro uso pratico sarebbe quello di supportare flussi di lavoro personalizzati nell'applicazione in base a regole definite dall'utente. 

 Ecco un po 'di codice MSDN sulla serializzazione di alberi di espressioni ( <http://code.msdn.microsoft.com/exprserialization> ) che dovrebbe far scorrere le idee. È possibile utilizzare [DataAdapter.FillSchema](http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldataadapter.fillschema.aspx) . <p>esistono diversi metodi per ottenere un piano di esecuzione, che uno da utilizzare dipenderà dalle circostanze. in genere è possibile utilizzare sql server management studio per ottenere un piano, tuttavia se per qualche motivo non è possibile eseguire la query in sql server management studio, potrebbe essere utile essere in grado di ottenere un piano tramite sql server profiler o ispezionando la cache del piano.</p><h2>metodo 1: utilizzo di sql server management studio</h2><p>sql server è dotato di un paio di funzionalità intuitive che rendono molto semplice l'acquisizione di un piano di esecuzione, semplicemente assicurati che la voce di menu &quot;includi piano di esecuzione effettivo&quot; (presente nel menu &quot;query&quot;) sia spuntata ed esegui la query come normale .</p><p><img src="https://i.stack.imgur.com/0icgu.png" alt="include action execution plan menu item"></p><p>se si sta tentando di ottenere il piano di esecuzione per le istruzioni in una stored procedure, è necessario eseguire la stored procedure, in questo modo:</p><pre><code>exec p\_example 42 </code></pre><p>una volta completata la tua query, dovresti visualizzare una scheda aggiuntiva intitolata &quot;piano di esecuzione&quot; nel riquadro dei risultati. se hai eseguito molte affermazioni, potresti vedere molti piani visualizzati in questa scheda.</p><p><img src="https://i.stack.imgur.com/ihkoe.png" alt="screenshot of an execution plan"></p><p>da qui è possibile ispezionare il piano di esecuzione in sql server management studio oppure fare clic con il tasto destro del mouse sul piano e selezionare &quot;salva piano di esecuzione con nome ...&quot; per salvare il piano in un file in formato xml.</p><h2>metodo 2 - utilizzo delle opzioni showplan</h2><p>questo metodo è molto simile al metodo 1 (in realtà questo è ciò che sql server management studio esegue internamente), tuttavia l'ho incluso per completezza o se non è disponibile sql server management studio.</p><p>prima di eseguire la query, eseguire <strong>uno</strong>delle seguenti affermazioni. l'istruzione deve essere l'unica dichiarazione nel batch, cioè non è possibile eseguire un'altra istruzione allo stesso tempo:</p><pre><code>set showplan\_text on set showplan\_all on set showplan\_xml on set statistics profile on set statistics xml on -- the is the recommended option to use </code></pre><p>queste sono opzioni di connessione e quindi è necessario eseguirlo solo una volta per connessione. da questo punto in poi tutte le istruzioni eseguite saranno accompagnate da un <strong>set di risultati aggiuntivi</strong>contenente il piano di esecuzione nel formato desiderato - è sufficiente eseguire la query come si farebbe normalmente per vedere il piano.</p><p>una volta che hai finito puoi disattivare questa opzione con la seguente dichiarazione:</p><pre><code>set &lt;&lt;option&gt;&gt; off </code></pre><h3>confronto dei formati del piano di esecuzione</h3><p>a meno che tu non abbia una forte preferenza, la mia raccomandazione è di usare l'opzione <code>statistics xml</code>. questa opzione è equivalente all'opzione &quot;includi piano di esecuzione effettivo&quot; in sql server management studio e fornisce la maggior parte delle informazioni nel formato più conveniente.</p><ul> <li><code>showplan\_text</code>: visualizza un piano di esecuzione stimato basato sul testo base, senza eseguire la query</li> <li><code>showplan\_all</code>: visualizza un piano di esecuzione stimato basato su testo con stime dei costi, senza eseguire la query</li> <li><code>showplan\_xml</code>: visualizza un piano di esecuzione stimato basato su xml con stime dei costi, senza eseguire la query. questo è equivalente all'opzione &quot;visualizza piano di esecuzione stimato ...&quot; in sql server management studio.</li> <li><code>statistics profile</code> - esegue la query e visualizza un piano di esecuzione effettivo basato sul testo.</li> <li><code>statistics xml</code> - esegue la query e visualizza un piano di esecuzione effettivo basato su xml. ciò equivale all'opzione &quot;includi piano di esecuzione effettiva&quot; in sql server management studio.</li> </ul><h2>metodo 3 - utilizzo di sql server profiler</h2><p>se non è possibile eseguire direttamente la query (o la query non viene eseguita lentamente quando viene eseguita direttamente - ricordare che vogliamo un piano di esecuzione della query non valido), è possibile acquisire un piano utilizzando una traccia di sql server profiler. l'idea è di eseguire la tua query mentre è in esecuzione una traccia che sta catturando uno degli eventi &quot;showplan&quot;.</p><p>si noti che a seconda del carico si <strong>può</strong>utilizzare questo metodo in un ambiente di produzione, tuttavia è necessario prestare attenzione. i meccanismi di definizione dei profili di sql server sono progettati per minimizzare l'impatto sul database ma ciò non significa che non be <em>any</em> impatto sulle prestazioni.potresti anche avere problemi nel filtrare e identificare il piano corretto nella tua traccia se il tuo database è in uso intensivo. dovresti ovviamente controllare con il tuo dba per vedere se sono contenti di averlo fatto sul loro prezioso database!</p><ol> <li>aprire sql server profiler e creare una nuova traccia connettendosi al database desiderato rispetto al quale si desidera registrare la traccia.</li> <li>sotto la scheda &quot;selezione eventi&quot; seleziona &quot;mostra tutti gli eventi&quot;, controlla la riga &quot;prestazioni&quot; -&gt; &quot;showplan xml&quot; ed esegui la traccia.</li> <li>mentre la traccia è in esecuzione, fare tutto ciò che è necessario per eseguire la query a esecuzione lenta.</li> <li>attendi il completamento della query e interrompi la traccia.</li> <li>per salvare la traccia, fare clic con il pulsante destro del mouse su xml del piano in sql server profiler e selezionare &quot;estrai dati evento ...&quot; per salvare il piano in file in formato xml.</li> </ol><p>il piano che ottieni è equivalente all'opzione &quot;includi piano di esecuzione effettivo&quot; in sql server management studio.</p><h2>metodo 4 - ispezione della cache delle query</h2><p>se non è possibile eseguire direttamente la query e non è possibile acquisire una traccia di profiler, è comunque possibile ottenere un piano stimato ispezionando la cache del piano di query sql.</p><p>esaminiamo la cache del piano interrogando sql server <a href="http://msdn.microsoft.com/en-us/library/ms188754.aspx">dmvs</a> . la seguente è una query di base che elencherà tutti i piani di query memorizzati nella cache (come xml) insieme al loro testo sql. nella maggior parte dei database sarà necessario aggiungere ulteriori clausole di filtro per filtrare i risultati fino ai soli piani a cui si è interessati.</p><pre><code>select usecounts, cacheobjtype, objtype, text, query\_plan from sys.dm\_exec\_cached\_plans cross apply sys.dm\_exec\_sql\_text(plan\_handle) cross apply sys.dm\_exec\_query\_plan(plan\_handle) </code></pre><p>esegui questa query e fai clic sul piano xml per aprire il piano in una nuova finestra - fai clic con il pulsante destro e seleziona &quot;salva piano di esecuzione come ...&quot; per salvare il piano in file in formato xml.</p><h1>gli appunti:</h1><p>poiché ci sono così tanti fattori coinvolti (che vanno dalla tabella e dallo schema dell'indice fino ai dati archiviati e alle statistiche della tabella) dovresti <strong>sempre</strong>prova ad ottenere un piano di esecuzione dal database che ti interessa (normalmente quello che sta vivendo un problema di prestazioni).</p><p>non è possibile acquisire un piano di esecuzione per le stored procedure crittografate.</p><h2>piani di esecuzione &quot;effettivi&quot; o &quot;stimati&quot;</h2><p>un piano di esecuzione <em>effettivo</em> è uno in cui sql server esegue effettivamente la query, mentre un <em>stimato</em>piano di esecuzione sql server elabora ciò che <em>would</em> fa senza eseguire la query. sebbene logicamente equivalente, un piano di esecuzione reale è molto più utile in quanto contiene ulteriori dettagli e statistiche su ciò che effettivamente è accaduto durante l'esecuzione della query. questo è essenziale quando si diagnosticano problemi in cui le stime di sql server non sono attive (ad esempio quando le statistiche non sono aggiornate).</p><ul> <li> <a href="http://sqlserverpedia.com/blog/sql-server-bloggers/estimated-and-actual-execution-plan-revisited/">piano di esecuzione stimato ed effettivo rivisto</a> </li> </ul><h2>come interpreto un piano di esecuzione della query?</h2><p>questo è un argomento degno di un (gratuito) <a href="https://www.simple-talk.com/books/sql-books/sql-server-execution-plans-second-edition-by-grant-fritchey/">libro</a> a sé stante.</p><h2>guarda anche:</h2><ul> <li> <a href="http://www.simple-talk.com/sql/performance/execution-plan-basics/">basi del piano di esecuzione</a> </li> <li> <a href="http://msdn.microsoft.com/en-us/library/ms178086.aspx">showplan batch di permessi e transact-sql</a> </li> <li> <a href="http://www.dbsnaps.com/sql-server/sql-server-query-hashes/">sql server 2008 - utilizzo degli hash di query e degli hash del piano di query</a> </li> <li> <a href="http://www.mssqltips.com/sqlservertip/1661/analyzing-the-sql-server-plan-cache/">analisi di sql server plan cache</a> </li> </ul> <p>dipende dal documento .php in cui ti trovi - se ti trovi in ​​item.php, o nei file category-item.php, dovrebbe funzionare quanto segue.</p><p>nella parte superiore del documento, aggiungi questo codice:</p><pre><code>&lt;!-- call to prepare extra fields --&gt; &lt;?php $extrafields = array(); foreach($this-&gt;item-&gt;extra\_fields as $item) { $extrafields[$item-&gt;id] = $item-&gt;value; } ?&gt; </code></pre><p>quindi, ovunque tu voglia chiamare il valore del campo compilato, usa questo:</p><pre><code>&lt;?php if($extrafields[id\_number\_of\_field]!=''):?&gt; &lt;!-- if filled in, then call data --&gt; &lt;?php echo $extrafields[id\_number\_of\_field];?&gt; &lt;!-- actual data call --&gt; &lt;?php endif; ?&gt; </code></pre><p>tag.php funziona in modo leggermente diverso, così come i moduli k2.</p><p>tag.php - non è necessario il codice aggiuntivo in testa, quanto segue chiamerà i dati del campo.</p><pre><code>&lt;?php $extrafields = json\_decode($item-&gt;extra\_fields);?&gt; &lt;?php foreach($extrafields as $key=&gt;$value): ?&gt; &lt;?php if($extrafields[$key]-&gt;id == 'id\_number\_of\_field'&amp;&amp;$extrafields[$key]-&gt;value!=''): ?&gt; &lt;?php echo $extrafields[$key]-&gt;value; ?&gt;, &lt;?php endif; ?&gt; &lt;?php endforeach; ?&gt; </code></pre><p>ancora una volta, con module\_k2\_content, non è necessaria la prima chiamata di dati. ottieni i dati sul campo in questo modo:</p><pre><code>&lt;?php echo $item-&gt;extrafields-&gt;alias\_of\_field-&gt;value ;?&gt; </code></pre><p>spero che sia d'aiuto.</p> <p>il driver del database aggiungerà nuovamente il risultato alla tabella dopo il salvataggio.</p><p>quindi, qualcosa come il prossimo dovrebbe funzionare:</p><pre><code>$table = $this-&gt;gettable(); if ($table-&gt;save($data)  true) { return $table-&gt;id; } else { return false; } </code></pre> <p>spesso, una condizione if lunga è il segno di codice che necessita di refactoring, ma a volte non è possibile evitarlo. in questi casi, preferisco il primo:</p><pre><code>if (bar || baz || quux) { ... } </code></pre><p>perché sei in grado di dire cosa sta succedendo con una riga. tuttavia, preferirei fare qualcosa del genere, quando possibile:</p><pre><code>function foo() { return bar || baz || quux; } if (foo()) { ... } </code></pre> Ovunque nel sistema, dove hai accesso a `MyContext` , fai questo: 


```
context.Database.GetDbConnection().GetType().Name

```
  Ad esempio, è `SqliteConnection` per SQLite o `SqlServerConnection` per SQL Server e così via. 

 **Tuttavia non sono sicuro di dover smaltire la connessione in seguito!** allora è molto semplice
se hai 4 ceppi e li vuoi in 2 parti 
fai 4 : 2 = 2
se hai 10 ceppi e vuoi 5 parti 
fai 10 : 5 = sempre 2 per parte
ma se hai 8 parti da riempire e hai 32 ceppi allora
32 : 8 = 4 per ogni parte
.
.è facilissomo fare le divisioni, basta usare una comune scalcolatrice,
io già che sono quì a sparare cavolate al computer, per le operazioni di cui sopra ho usato la scaccolatrice che ho troiato nei programmi del menù avvio, alla sezione accesssori
.
ciao cara, spego di esserti stato, non utile, ma superutilissimissimo