Qualcuno ha un elenco completo di metodi e metodi di estensione LINQPad, come ad esempio
.Dump()
SubmitChanges()
Qualcuno ha un elenco completo di metodi e metodi di estensione LINQPad, come ad esempio
.Dump()
SubmitChanges()
Risposte:
LINQPad definisce due metodi di estensione (in LINQPad.Extensions), vale a dire Dump()
e Disassemble()
. Dump()
scrive nella finestra di output utilizzando il formattatore di output di LINQPad ed è sovraccarico per consentire di specificare un'intestazione:
typeof (int).Assembly.Dump ();
typeof (int).Assembly.Dump ("mscorlib");
È inoltre possibile specificare una profondità massima di ricorsione per sostituire il valore predefinito di 5 livelli:
typeof (int).Assembly.Dump (1); // Dump just one level deep
typeof (int).Assembly.Dump (7); // Dump 7 levels deep
typeof (int).Assembly.Dump ("mscorlib", 7); // Dump 7 levels deep with heading
Disassemble () disassembla qualsiasi metodo IL
, restituendo l'output in una stringa:
typeof (Uri).GetMethod ("GetHashCode").Disassemble().Dump();
Oltre a questi due metodi di estensione, ci sono alcuni metodi statici utili in LINQPad.Util. Questi sono documentati in completamento automatico e includono:
LINQPad fornisce anche la classe HyperLinq. Questo ha due scopi: il primo è visualizzare i normali collegamenti ipertestuali:
new Hyperlinq ("www.linqpad.net").Dump();
new Hyperlinq ("www.linqpad.net", "Web site").Dump();
new Hyperlinq ("mailto:user@domain.com", "Email").Dump();
Puoi combinarlo con Util.HorizontalRun
:
Util.HorizontalRun (true,
"Check out",
new Hyperlinq ("http://stackoverflow.com", "this site"),
"for answers to programming questions.").Dump();
Risultato:
Dai un'occhiata a questo sito per le risposte alle domande di programmazione.
Il secondo scopo di HyperLinq è creare dinamicamente query:
// Dynamically build simple expression:
new Hyperlinq (QueryLanguage.Expression, "123 * 234").Dump();
// Dynamically build query:
new Hyperlinq (QueryLanguage.Expression, @"from c in Customers
where c.Name.Length > 3
select c.Name", "Click to run!").Dump();
Puoi anche scrivere i tuoi metodi di estensione in LINQPad. Vai su "Le mie query" e fai clic sulla query chiamata "Le mie estensioni". Tutti i tipi / metodi che definiscono qui sono accessibili a tutte le query:
void Main()
{
"hello".Pascal().Dump();
}
public static class MyExtensions
{
public static string Pascal (this string s)
{
return char.ToLower (s[0]) + s.Substring(1);
}
}
In 4.46 (.02) sono state introdotte nuove classi e metodi :
Inoltre, la classe Hyperlinq ora supporta un delegato Action che verrà chiamato quando si fa clic sul collegamento, consentendo di reagire ad esso nel codice e non solo di collegarsi a pagine Web esterne.
DumpContainer
è una classe che aggiunge un blocco nella finestra di output a cui può essere sostituito il contenuto.
NOTA! Ricordarsi .Dump()
della DumpContainer
stessa nel punto appropriato.
Usare:
var dc = new DumpContainer();
dc.Content = "Test";
// further down in the code
dc.Content = "Another test";
OnDemand
è un metodo di estensione che non produrrà il contenuto del suo parametro nella finestra di output, ma aggiungerà invece un link cliccabile, che se cliccato sostituirà il link con il .Dump()
contenuto ed del parametro. Questo è ottimo per le strutture di dati a volte necessarie che sono costose o occupano molto spazio.
NOTA! Ricorda .Dump()
i risultati della chiamata OnDemand
nel punto appropriato.
Per usarlo:
Customers.OnDemand("Customers").Dump(); // description is optional
Util.ProgressBar
è una classe che può mostrare una barra di avanzamento grafica all'interno della finestra di output, che può essere modificata man mano che il codice procede.
NOTA! Ricordare .Dump()
l'oggetto Util.ProgressBar nel punto appropriato.
Per usarlo:
var pb = new Util.ProgressBar("Analyzing data");
pb.Dump();
for (int index = 0; index <= 100; index++)
{
pb.Percent = index;
Thread.Sleep(100);
}
Oltre al noto myQuery.Dump("Query result:")
, un'altra caratteristica da menzionare è la Util
classe: contiene molti metodi abbastanza utili (alcuni dei quali ho menzionato, ma ce ne sono molti altri).
Inoltre è interessante che puoi modificare il modo in cui Dump()
funziona .
Infine, ti mostrerò come rendere permanenti le modifiche (ad es. Inserire, aggiornare, eliminare le query LINQ) utilizzando SubmitChanges()
o SaveChanges()
come accedere all'oggetto di connessione interno di LinqPad.
E per arrotondare, ti mostrerò come è possibile creare una semplice grafica 2d all'interno di LinqPad (disegnare linee, bitmap o funzioni ).
Quindi, ecco una raccolta di funzionalità LinqPad integrate (dalla mia esperienza con lo strumento):
(parametri disponibili in LinqPad v5.03.08 e versioni successive)
Tutti gli utenti di LinqPad conoscono e adorano il .Dump()
metodo di estensione, che consuma e stampa (quasi) tutto.
Ma sapevi che ci sono un paio di parametri disponibili? Dai un'occhiata a questo frammento di codice:
var obj=new { a="Hello", b=5, c="World", d=new { y=5, z=10 } };
obj.Dump(description: "1st example", depth: 5, toDataGrid: false, exclude: "b,d");
obj.Dump("2nd example", exclude: "a,c");
obj.Dump("2nd example", exclude: "+b,d"); // new in V5.06.06 beta
Le prime esempio stampe solo variabili a
e c
e nasconde b
e d
, il 2 ° esempio fa il contrario (nota che specifica solo 2 dei parametri disponibili). Le variabili y
e z
non possono essere nascoste singolarmente, perché non sono al livello più alto.
Sono disponibili i seguenti parametri ( tutti facoltativi ):
description
[stringa] - fornisce una descrizione per il dump dell'oggettodepth
[int?] - limita la profondità di ispezione ricorsiva degli oggettitoDataGrid
[bool] - se vero, l'output è formattato come datagrid anziché come RichTextexclude
[stringa] - se si fornisce un elenco di variabili separato da virgole, verranno esclusi dall'output (nell'esempio "a, c": b
e d
vengono visualizzati a
e c
nascosti)exclude
[stringa] con prefisso "+" - il prefisso inverte la logica del parametro exclude. Ciò significa che se si fornisce un elenco di variabili separato da virgole, tutte tranne quelle specificate vengono nascoste (nell'esempio "+ b, d": b
e d
vengono visualizzate, tutte le altre nascoste)var x=Util.ToExpando(obj, "a, c", "b, d"); x.Dump();
.OnDemand("click me").Dump();
invece di .Dump()
, verrà visualizzato un collegamento su cui è possibile fare clic per espandere. Utile se si desidera controllare i valori, ad esempio Util.OnDemand("Customer-ID: " + customerObject.ID.ToString(), ()=>customerObject, false).Dump();
per mostrare sempre l'ID per impostazione predefinita, ma rivelare i dettagli customerObject
solo se si è interessati.Argomenti più avanzati su Dump sono disponibili qui e là .
Questa non è un'estensione LinqPad, ma piuttosto una classe .NET, ma poiché è utile, lo citerò comunque. Puoi ottenere molte informazioni utili che puoi utilizzare nei tuoi script come:
Environment.UserDomainName.Dump();
Environment.MachineName.Dump();
Environment.UserName.Dump();
Environment.CurrentDirectory.Dump();
Environment.SystemDirectory.Dump();
NB Per ottenere Domain\UserName
vorrei usare System.Security.Principal.WindowsIdentity.GetCurrent().Name
piuttosto che Environment.UserDomainName+@"\"+Environment.UserName
.
( novità: disponibile dalla versione LinqPad v4.45.05 (beta) )
Util.WriteCsv (Customers, @"c:\temp\customers.csv");
Questo scriverà il contenuto della tabella Customers
nel file CSV c:\temp\customers.csv
. Puoi anche trovare un buon esempio su come usare Util.WriteCsv
e quindi visualizzare i dati CSV nella finestra dei risultati di Linqpad qui .
suggerimenti:
Per ottenere / creare un file CSV che si trova nella stessa directory della query, è possibile utilizzare:
var csvFile=Util.CurrentQueryPath.Replace(".linq", ".csv");
Se la tabella è grande, utilizzare ObjectTrackingEnabled = false;
prima di scrivere il CSV per evitare di memorizzarlo nella memoria cache.
Se si desidera generare una tabella in formato XML anziché come file separato da virgole, è possibile farlo come segue :
var xmlFile=Util.CurrentQueryPath.Replace(".linq", ".xml");
var xml = XElement.Load(xmlFile);
var query =
from e in xml.Elements()
where e.Attribute("attr1").Value == "a"
select e;
query.Dump();
In questo esempio vengono restituiti tutti gli elementi con l'attributo attr1
che contiene il valore "a"
di un file XML che ha lo stesso nome della query ed è contenuto nello stesso percorso. Dai un'occhiata a questo link per altri esempi di codice.
var pwd = Util.GetPassword("UserXY");
Ciò recupererà la password dal gestore password integrato di LinqPad. Per creare e modificare la password, aprire il menu "Password Manager" nel menu "File" di LINQPad. Se non viene salvata alcuna password quando si esegue il codice C #, si aprirà una finestra di dialogo della password che richiede la password e si ha la possibilità di crearla e salvarla al volo selezionando la casella di controllo Salva password (nell'esempio, la password per "UserXY" verrebbe salvato e in seguito puoi trovare questa voce nel gestore delle password ).
I vantaggi sono che è possibile memorizzare la password negli script Linq creati in modo sicuro, separatamente e crittografati nel profilo utente di Windows (è archiviato %localappdata%\LINQPad\Passwords
come file). LinqPad utilizza DPAPI di Windows per proteggere la password.
Inoltre, la password viene archiviata centralmente, quindi se è necessario modificarla, è possibile farlo nel menu e si applica immediatamente a tutti gli script creati.
Appunti:
Se non si desidera salvare la password e visualizzare semplicemente una finestra di dialogo della password, è possibile utilizzare il secondo parametro nel modo seguente: In
var pwd = Util.GetPassword("UserXY", true);
questo modo la casella di controllo Salva password verrà deselezionata nella finestra di dialogo della password (tuttavia, l'utente è ancora in grado di controllarla e scegliere di salvare comunque).
Se richiedi che la password sia archiviata in a SecureString
, puoi utilizzare questa funzione di supporto (nb: per ottenere il metodo di estensione .ToSecureString()
utilizzato, segui questo link su Stackoverflow - ti consente anche di riconvertirlo se necessario):
System.Security.SecureString GetPasswordSecure(string Name, bool noDefaultSave=true)
{
return Util.GetPassword(Name, noDefaultSave)
.ToSecureString();
}
Questo metodo funziona come un processore di comandi. Puoi richiamare tutti i comandi che conosci dalla console di Windows.
Esempio 1 - dir:
Util.Cmd(@"dir C:\");
Questo produrrà il risultato della directory senza che sia necessario .Dump
. La sua memorizzazione in una variabile ha il vantaggio di poter utilizzare ulteriori query Linq su di essa. Per esempio:
var path=@"C:\windows\system32";
var dirSwitch="/s/b";
var x=Util.Cmd(String.Format(@"dir ""{0}"" {1}", path, dirSwitch), true);
var q=from d in x
where d.Contains(".exe") || d.Contains(".dll")
orderby d
select d;
q.Dump();
Questo scaricherà tutti i file con estensione ".exe" o ".dll" contenuti in C:\windows\system32
. L' /s
opzione viene utilizzata per richiamare tutte le sottodirectory e /b
viene utilizzata per il formato di output non elaborato. Si noti che il secondo parametro del metodo Cmd è specificato per sopprimere l'output della console al fine di mostrare solo il risultato filtrato utilizzando il metodo Dump.
Puoi vedere che questo è più flessibile dei caratteri jolly che hai con dir
poiché puoi utilizzare la piena flessibilità del motore di query di Linq.
Esempio 2 - editor di testo:
Puoi aprire un file nel Blocco note in questo modo:
var filePath=@"C:\HelloWorld.txt";
Util.Cmd(@"%systemroot%\system32\notepad.exe", filePath);
Visualizza immagini da un URL. Esempio:
var url = "http://chart.apis.google.com/chart?cht=p3&chd=s:Uf9a&chs=350x140&chl=January|February|March|April";
Util.Image(url).Dump();
L'uso Util.ProgressBar
consente di visualizzare una barra di avanzamento. È possibile utilizzare la seguente classe di supporto:
public class ProgressBar
{
Util.ProgressBar prog;
public ProgressBar()
{
Init("Processing");
}
private void Init(string msg)
{
prog = new Util.ProgressBar (msg).Dump();
prog.Percent=0;
}
public void Update(int percent)
{
Update(percent, null);
}
public void Update(int percent, string msg)
{
prog.Percent=percent;
if (String.IsNullOrEmpty(msg))
{
if (percent>99) prog.Caption="Done.";
}
else
{
prog.Caption=msg;
}
}
}
Usalo semplicemente come mostra il seguente esempio:
void Main()
{
var pb1= new ProgressBar();
Thread.Sleep(50);
pb1.Update(50, "Doing something"); Thread.Sleep(550);
pb1.Update(100); Thread.Sleep(50);
}
In alternativa, è possibile utilizzare Util.Progress
per aggiornare la barra di avanzamento integrata di LinqPad, ad esempio:
Util.Progress = 25; // 25 percent complete
La differenza è che non verrà visualizzato nella finestra dei risultati e non è possibile assegnargli un messaggio.
Visualizza HTML nella finestra di output. Esempio:
Util.RawHtml (new XElement ("h1", "This is a big heading")).Dump();
È possibile utilizzare questa funzione di esempio
public void ShowUrl(string strURL, string Title)
{
Action showURL = delegate() { Process.Start("iexplore.exe", strURL); };
var url = new Hyperlinq(showURL, "this link", true);
Util.HorizontalRun (true, "Click ", url, " for details.").Dump(Title);
}
per mostrare i collegamenti ipertestuali nella finestra dei risultati o qualsiasi azione come l'apertura dell'editor preferito. Uso:
ShowUrl("http://stackoverflow.com", "Check out StackOverflow");
Nota che questa funzione è sempre attiva, mentre new Hyperlinq ("http://myURL", "Web site").Dump();
non funziona per alcuni tipi di URL (in particolare, se devi passare nomi di porte come ": 1234" come parte dell'URL).
Legge l'input dalla console. Esempio:
int age = Util.ReadLine<int> ("Enter your age");
Come sinonimo di Util.ReadLine<string>()
, puoi anche usare Console.ReadLine()
.
Ma c'è di più! È possibile creare un semplice parser JSON con il seguente frammento: molto utile, ad esempio se si desidera analizzare e testare una stringa JSON al volo. Salvare il seguente frammento come JSONAnalyzer.linq usando un editor di testo e quindi aprirlo in LinqPad (questo per aggiungere facilmente i riferimenti al volo):
<Query Kind="Program">
<Reference><RuntimeDirectory>\System.Web.Extensions.dll</Reference>
<Namespace>System.Web.Script.Serialization</Namespace>
</Query>
void Main()
{
var jsonData=Util.ReadLine<string>("Enter JSON string:");
var jsonAsObject = new JavaScriptSerializer().Deserialize<object>(jsonData);
jsonAsObject.Dump("Deserialized JSON");
}
Ora puoi eseguirlo e incollare semplicemente una stringa JSON dagli Appunti nella console - utilizzerà la Dump
funzione per visualizzarlo correttamente come oggetto - e otterrai anche i messaggi di errore del parser sullo schermo per risolvere i problemi. Molto utile per il debug di AJAX.
Se è necessario cancellare la finestra dei risultati all'interno dello script, utilizzare:
Util.ClearResults();
Utilizzalo nella parte superiore dello script oppure, se esegui più query in uno script, dovresti attendere l'input dell'utente prima di svuotare lo schermo (ad esempio, precedendolo con Util.ReadLine
).
Inoltre è interessante poter cambiare l'output del .Dump()
metodo. Basta implementare l'interfaccia ICustomMemberProvider
, ad es
public class test : ICustomMemberProvider
{
IEnumerable<string> ICustomMemberProvider.GetNames() {
return new List<string>{"Hint", "constMember1", "constMember2", "myprop"};
}
IEnumerable<Type> ICustomMemberProvider.GetTypes()
{
return new List<Type>{typeof(string), typeof(string[]),
typeof(string), typeof(string)};
}
IEnumerable<object> ICustomMemberProvider.GetValues()
{
return new List<object>{
"This class contains custom properties for .Dump()",
new string[]{"A", "B", "C"}, "blabla", abc};
}
public string abc = "Hello1"; // abc is shown as "myprop"
public string xyz = "Hello2"; // xyz is entirely hidden
}
Se crei un'istanza di questa classe, ad esempio
var obj1 = new test();
obj1.Dump("Test");
allora il risultato sarà solo Hint
, constMember1
, constMember2
, e myprop
, ma non di proprietà xyz
:
Se devi visualizzare una finestra di messaggio, guarda qui come farlo.
Ad esempio, è possibile visualizzare un InputBox utilizzando il seguente codice
void Main()
{
string inputValue="John Doe";
inputValue=Interaction.InputBox("Enter user name", "Query", inputValue);
if (!string.IsNullOrEmpty(inputValue)) // not cancelled and value entered
{
inputValue.Dump("You have entered;"); // either display it in results window
Interaction.MsgBox(inputValue, MsgBoxStyle.OkOnly, "Result"); // or as MsgBox
}
}
(non dimenticare di premere F4 e aggiungere Microsoft.VisualBasic.dll e i suoi spazi dei nomi per farlo funzionare)
( novità: disponibile dalla versione LinqPad v4.52.1 (beta) )
Consente di eseguire un altro script LINQPad dall'interno dello script o all'interno del proprio programma .NET o servizio Windows (facendo riferimento alla versione LINQPad4-AnyCPU di LINQPad.exe
). Esegue lo script proprio come lo lprun.exe
farebbe lo strumento da riga di comando .
Esempi:
const string path=@"C:\myScripts\LinqPad\";
var dummy=new LINQPad.QueryResultFormat(); // needed to call Util.Run
Util.Run(path+"foo.linq", dummy);
Questo esempio esegue lo script foo.linq
, che contiene il seguente codice di esempio:
void Main(string[] args)
{
#if CMD
"I'm been called from lprun! (command line)".Dump();
#else
"I'm running in the LINQPad GUI!".Dump();
args = new[] { "testhost", "test@foo.com", "test@foo.com", "Test Subject" };
#endif
args.Dump("Args");
}
Consente di verificare se lo script è stato eseguito dall'interno della GUI di LinqPad o tramite lprun.exe
o con Util.Run
.
Nota: le seguenti varianti di invocazione potrebbero essere utili:
Util.Run(path+"foo.linq", dummy).Dump(); // obviously dumps the script output!
Util.Run(path+"foo.linq", dummy).Save(path+"foo.log"); // writes output into log
Util.Run(path+"foo.linq", dummy).SaveAsync(path+"foo1.log"); // async output log
Se stai usando LinqToSQL , potresti voler rendere permanenti le modifiche (per operazioni di inserimento / aggiornamento / eliminazione ). Poiché il contesto del database è implicitamente creato da LinqPad, è necessario chiamare SubmitChanges()
dopo ogni modifica come mostrato di seguito.
Esempi per il database (LinqPad-) Northwind :
Inserire
var newP = new Products() { ProductID=pID, CategoryID=cID,
ProductName="Salmon#"+pID.ToString() };
Products.InsertOnSubmit(newP);
SubmitChanges();
Aggiornare
var prod=(from p in Products
where p.ProductName.Contains("Salmon")
select p).FirstOrDefault();
prod.ProductName="Trout#"+prod.ProductID.ToString();
SubmitChanges();
Elimina
var itemsToDelete=Products.Where(p=> p.ProductName.Contains("Salmon") ||
p.ProductName.Contains("Trout"));
foreach(var item in itemsToDelete) { Products.DeleteOnSubmit(item); }
SubmitChanges();
Nota: per ottenere ID validi per gli esempi precedenti, è possibile utilizzare:
var cID = (from c in Categories
where c.CategoryName.Contains("Seafood")
select c).FirstOrDefault().CategoryID;
var pID = Products.Count()+1;
prima di invocarli.
Se si utilizza Entity Framework , è possibile che si desideri rendere permanenti anche le modifiche (per operazioni di inserimento / aggiornamento / eliminazione ). Poiché il contesto del database è implicitamente creato da LinqPad, è necessario chiamare SaveChanges()
dopo ogni modifica come mostrato di seguito.
Gli esempi sono sostanzialmente gli stessi di prima per LinqToSQL , ma è necessario utilizzarli SaveChanges()
, e anche per inserire ed eliminare i metodi sono cambiati.
Inserire
var newP = new Products() { ProductID=pID, CategoryID=cID,
ProductName="Salmon#"+pID.ToString() };
Products.Add(newP);
SaveChanges();
Aggiornare
var prod=(from p in Products
where p.ProductName.Contains("Salmon")
select p).FirstOrDefault();
prod.ProductName="Trout#"+prod.ProductID.ToString();
SaveChanges();
Elimina
var itemsToDelete=Products.Where(p=> p.ProductName.Contains("Salmon") ||
p.ProductName.Contains("Trout"));
foreach(var item in itemsToDelete) { Products.Remove(item); }
SaveChanges();
Nota: per ottenere ID validi per gli esempi precedenti, è possibile utilizzare:
var cID = (from c in Categories
where c.CategoryName.Contains("Seafood")
select c).FirstOrDefault().CategoryID;
var pID = Products.Count()+1;
prima di invocarli.
In LinqPad , il contesto del database viene applicato automaticamente utilizzando la casella combinata in alto e selezionando il database giusto per la query. Ma a volte è utile fare riferimento in modo esplicito, ad esempio se si copia un codice dal progetto da Visual Studio e lo si incolla in LinqPad.
Lo snippet di codice preso dal progetto Visual Studio molto probabilmente è simile al seguente:
var prod=(from p in dc.Products
where p.ProductName.Contains("Salmon")
select p).FirstOrDefault();
prod.ProductName="Trout#"+prod.ProductID.ToString();
dc.SaveChanges();
Ora, che cosa fare con dc
? Naturalmente, è possibile rimuovere ogni occorrenza di dc.
nella query, ma è molto più semplice. Aggiungi
var dc=this; // UserQuery
nella parte superiore dello snippet in questo modo:
void Main()
{
var dc=this;
var prod=(from p in dc.Products
where p.ProductName.Contains("Salmon")
select p).FirstOrDefault();
prod.ProductName="Trout#"+prod.ProductID.ToString();
dc.SaveChanges();
}
e il codice funzionerà all'istante!
Utilizzando LinqPad con OleDb, convertendo un datatable in oggetto Linq, query SQL in Linq
Il seguente frammento di codice consente di utilizzare LinqPad con OleDb. Aggiungere System.Data.OleDb
dalla System.Data
assemblea per le proprietà della query, quindi incollare il seguente codice in Main()
:
var connStr="Provider=SQLOLEDB.1;"+this.Connection.ConnectionString;
OleDbConnection conn = new OleDbConnection(connStr);
DataSet myDS = new DataSet();
conn.Open();
string sql = @"SELECT * from Customers";
OleDbDataAdapter adpt = new OleDbDataAdapter();
adpt.SelectCommand = new OleDbCommand(sql, conn);
adpt.Fill(myDS);
myDS.Dump();
Ora aggiungi una connessione SqlServer a LinqPad e aggiungi il database Northwind per eseguire questo esempio.
NB: Se vuoi solo ottenere il database e il server della connessione attualmente selezionata, puoi usare questo frammento di codice:
void Main()
{
var dc=this;
var tgtSrv=dc.Connection.DataSource;
var tgtDb=dc.Connection.ConnectionString.Split(';').Select(s=>s.Trim())
.Where(x=>x.StartsWith("initial catalog", StringComparison.InvariantCultureIgnoreCase))
.ToArray()[0].Split('=')[1];
tgtSrv.Dump();
tgtDb.Dump();
}
Puoi persino convertire myDS
in Linq, le risposte alla seguente domanda mostrano come farlo: Belli esempi di utilizzo della parola chiave dinamica .NET 4 con Linq
Un altro esempio: supponiamo che il tuo DBA ti dia una query SQL e desideri analizzare i risultati in LinqPad - ovviamente in Linq, non in SQL. Quindi è possibile effettuare le seguenti operazioni:
void Main()
{
var dc=this;
// do the SQL query
var cmd =
"SELECT Orders.OrderID, Orders.CustomerID, Customers.CompanyName,"
+" Customers.Address, Customers.City"
+" FROM Customers INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID";
var results = dc.ExecuteQuery<OrderResult>(cmd);
// just get the cities back, ordered ascending
results.Select(x=>x.City).Distinct().OrderBy(x=>x).Dump();
}
class OrderResult
{ // put here all the fields you're returning from the SELECT
public dynamic OrderID=null;
public dynamic CustomerID=null;
public dynamic CompanyName=null;
public dynamic Address=null;
public dynamic City=null;
}
In questo esempio, la query SELECT del DBA viene semplicemente "inserita" nel testo del comando e i risultati vengono filtrati e ordinati per Città.
Naturalmente, questo è un esempio semplificato, il tuo DBA probabilmente ti darebbe uno script più complesso, ma stai ottenendo l'idea: basta aggiungere una classe di risultati di supporto che contiene tutti i campi dalla clausola SELECT e quindi puoi usarlo direttamente .
Puoi anche prendere il risultato da una procedura memorizzata in questo modo e usarlo in Linq. Come puoi vedere, in questo esempio non mi interessa il tipo di dati e lo uso dynamic
per esprimerlo.
Quindi si tratta davvero di una programmazione rapida per poter analizzare rapidamente i dati. Non dovresti farlo nella tua vera applicazione per vari motivi (iniezione SQL, perché puoi usare EF dall'inizio ecc.).
Disegna grafica in LinqPad, parte 1
Per utilizzare gli esempi di seguito, premere F4e aggiungere System.Windows.dll
, System.Windows.Forms.dll
, WindowsFormsIntegration.dll
, PresentationCore.dll
e PresentationFramework.dll
al vostro programma LINQPad e anche aggiungere lo spazio dei nomi System.Windows.Shapes
.
Il primo esempio disegna semplicemente una linea:
var myLine = new Line();
myLine.Stroke = System.Windows.Media.Brushes.LightSteelBlue;
myLine.X1 = 1; myLine.X2 = 50;
myLine.Y1 = 1; myLine.Y2 = 50;
myLine.StrokeThickness = 2;
PanelManager.DisplayWpfElement(myLine, "Graphic");
Il secondo esempio mostra come visualizzare gli elementi grafici in LinqPad usando PanelManager. Normalmente LinqPad supporta solo oggetti Wpf. Questo esempio usa System.Windows.Forms.Integration.WindowsFormsHost
per rendere Windows.Forms.PictureBox
disponibile (è stato ispirato da questo ):
// needs (F4): System.Windows.dll, System.Windows.Forms.dll,
// WindowsFormsIntegration.dll, PresentationCore.dll, PresentationFramework.dll
void Main()
{
var wfHost1 = new System.Windows.Forms.Integration.WindowsFormsHost();
wfHost1.Height=175; wfHost1.Width=175; wfHost1.Name="Picturebox1";
wfHost1.HorizontalAlignment=System.Windows.HorizontalAlignment.Left;
wfHost1.VerticalAlignment=System.Windows.VerticalAlignment.Top;
System.Windows.Forms.PictureBox pBox1 = new System.Windows.Forms.PictureBox();
wfHost1.Child = pBox1;
pBox1.Paint += new System.Windows.Forms.PaintEventHandler(picturebox1_Paint);
PanelManager.StackWpfElement(wfHost1, "Picture");
}
public string pathImg
{
get { return System.IO.Path.Combine(@"C:\Users\Public\Pictures\Sample Pictures\",
"Tulips.jpg"); }
}
// Define other methods and classes here
public void picturebox1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
// https://stackoverflow.com/a/14143574/1016343
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(pathImg);
System.Drawing.Point ulPoint = new System.Drawing.Point(0, 0);
e.Graphics.DrawImage(bmp, ulPoint.X, ulPoint.Y, 175, 175);
}
Questo creerà il seguente grafico (gli elementi del pannello "Grafica" e "Immagine" sono aggiunti dagli esempi sopra):
Se si desidera visualizzare le immagini dal database Northwind, è possibile effettuare le seguenti operazioni:
Modificare il nome del file immagine in "NorthwindPics.jpg", quindi aggiungere il codice seguente all'inizio del metodo Main () del secondo esempio :
var img = (from e in this.Employees select e).FirstOrDefault().Photo.ToArray();
using (FileStream fs1 = new FileStream(pathImg, FileMode.Create))
{
const int offset=78;
fs1.Write(img, offset, img.Length-offset);
fs1.Close();
}
Leggerà il primo record dalla tabella Employees e visualizzerà l'immagine.
Per ulteriori informazioni, consultare i seguenti collegamenti:
Forme e disegni di base nei visualizzatori personalizzati WPF
LinqPad
Nota: è possibile ottenere lo stesso risultato anche con PanelManager, come mostra il seguente esempio, che ho visto qui :
// using System.Drawing;
using (var image=new Bitmap(100, 100))
using (var gr = Graphics.FromImage(image))
{
gr.FillRectangle(Brushes.Gold, 0, 0, 100, 100);
gr.DrawEllipse(Pens.Blue, 5, 5, 90, 90);
gr.Save();
image.Dump();
}
Sta usando il .Dump()
comando per visualizzarlo. Puoi invocare image.Dump()
più volte e verrà aggiunta l'immagine.
Disegna grafica in LinqPad, parte 2
L'esempio seguente, ispirato a questo post, mostra come implementare un semplice plotter funzionale in Linqpad 5 usando C # 7:
void Main()
{
fnPlotter(x1: -1, x2: 1, fn: (double x) => Math.Pow(x, 3)).Dump();
}
public static Bitmap fnPlotter(double x1=-3, double x2=3, double s=0.05,
double? ymin=null, double? ymax=null,
Func<double, double> fn = null, bool enable3D=true)
{
ymin = ymin ?? x1; ymax = ymax ?? x2;
dynamic fArrPair(double p_x1 = -3, double p_x2 = 3, double p_s = 0.01,
Func<double, double> p_fn = null)
{
if (p_fn == null) p_fn = ((xf) => { return xf; }); // identity as default
var xl = new List<double>(); var yl = new List<double>();
for (var x = p_x1; x <= p_x2; x += p_s)
{
double? f = null;
try { f = p_fn(x); }
finally
{
if (f.HasValue) { xl.Add(x); yl.Add(f.Value); }
}
}
return new { Xs = xl.ToArray(), Ys = yl.ToArray() };
}
var chrt = new Chart(); var ca = new ChartArea(); chrt.ChartAreas.Add(ca);
ca.Area3DStyle.Enable3D = enable3D;
ca.AxisX.Minimum = x1; ca.AxisX.Maximum = x2;
ca.AxisY.Minimum = ymin.Value; ca.AxisY.Maximum = ymax.Value;
var sr = new Series(); chrt.Series.Add(sr);
sr.ChartType = SeriesChartType.Spline; sr.Color = Color.Red;
sr.MarkerColor = Color.Blue; sr.MarkerStyle = MarkerStyle.Circle;
sr.MarkerSize = 2;
var data = fArrPair(x1, x2, s, fn); sr.Points.DataBindXY(data.Xs, data.Ys);
var bm = new Bitmap(width: chrt.Width, height: chrt.Height);
chrt.DrawToBitmap(bm, chrt.Bounds); return bm;
}
Sta usando la capacità di LinqPad per visualizzare i moduli di Windows nel pannello dei risultati.
Aggiungere riferimenti (stampa ) : , , e aggiungere tutti gli spazi dei nomi da queste assemblee.
F4
System.Drawing.dll
System.Windows.Forms.dll
System.Windows.Forms.DataVisualization.dll
Suggerimenti aggiuntivi / ulteriori letture:
Vuoi usare LinqPad in Visual Studio ? Ecco come puoi farlo .
Devi avere LinqPad come "app portatile" ? Leggi qui come farlo.
Il sito Web di Joe per LinqPad è sempre un'ottima fonte. All'interno di LinqPad, Help -> What's New
offre suggerimenti su nuove funzioni e metodi. Il forum LinqPad contiene anche suggerimenti utili.
Anche molto utile: questo articolo sul debug di Linq (Pad).
Utilizzare lprun.exe
per eseguire query LINQ negli script batch. Leggi questo articolo per maggiori dettagli. Ad esempio:
echo Customers.Take(100) > script.txt
lprun -lang=e -cxname=CompanyServer.CustomerDb script.txt
in questo esempio, la query è una semplice espressione LINQ. Ovviamente, puoi preparare anche query complesse usando -lang=program
per attivare la modalità programma.
È possibile scrivere metodi di estensione e memorizzarli nella scheda Le mie query sul lato sinistro di LinqPad: L'ultimo elemento dell'albero è denominato Le mie estensioni ; fare doppio clic su di esso per aprire un file in cui è possibile scrivere estensioni disponibili per tutte le query. Inseriscili semplicemente nella classe statica pubblica MyExtensions
e usa il Main()
metodo per includere i test per le tue estensioni.
Il dump è un metodo di estensione globale e SubmitChanges proviene dall'oggetto DataContext che è un oggetto System.Data.Linq.DataContext.
LP aggiunge solo Dump e Disassemble per quanto ne so. Anche se consiglio vivamente di aprirlo in Reflector per vedere cos'altro c'è che può essere utilizzato. Una delle cose più interessanti è lo spazio dei nomi LINQPad.Util che ha alcune chicche utilizzate internamente da LINQPad.
.Dump()
o su qualsiasi altro metodo nell'editor di origine, premere F12 per "riflettere". Questo è ora integrato nello strumento!
Ho raggiunto il limite di testo StackOverflow nella mia risposta precedente , ma ci sono ancora estensioni più interessanti in LinqPad. Uno di questi vorrei menzionare:
.Dump()
)Dalla versione 5.42 beta di LinqPad puoi incorporare funzioni JavaScript e chiamarle direttamente dal tuo codice C #. Sebbene ciò abbia alcune limitazioni (rispetto a JSFiddle), è un buon modo per testare rapidamente un codice JavaScript in LinqPad.
Esempio:
void Main()
{
// JavaScript inside C#
var literal = new LINQPad.Controls.Literal("script",
@"function jsFoo(x) {
alert('jsFoo got parameter: ' + x);
var a = ['x', 'y', 'z']; external.log('Fetched \'' + a.pop() + '\' from Stack');
external.log('message from C#: \'' + x + '\'');
}");
// render & invoke
literal.Dump().HtmlElement.InvokeScript(true, "jsFoo", "testparam");
}
In questo esempio, una funzione jsFoo
con un parametro viene preparata e memorizzata nella variabile literal
. Quindi, viene renderizzato e chiamato via .Dump().HtmlElement.InvokeScript(...)
, passando il parametro testparam
.
La funzione JavaScript utilizza external.Log(...)
per generare testo nelle finestre di output di LinqPad e alert(...)
per visualizzare un messaggio popup.
Puoi semplificarlo aggiungendo i seguenti metodi / classi di estensione:
public static class ScriptExtension
{
public static object RunJavaScript(this LINQPad.Controls.Literal literal,
string jsFunction, params object[] p)
{
return literal.Dump().HtmlElement.InvokeScript(true, jsFunction, p);
}
public static LINQPad.Controls.Literal CreateJavaScript(string jsFunction)
{
return new LINQPad.Controls.Literal("script", jsFunction);
}
}
Quindi puoi chiamare l'esempio precedente come segue:
// JavaScript inside C#
var literal = ScriptExtension.CreateJavaScript(
@"function jsFoo(x) {
alert('jsFoo got parameter: ' + x);
var a = ['x', 'y', 'z']; external.log('Fetched \'' + a.pop() + '\' from Stack');
external.log('message from C#: \'' + x + '\'');
}");
// render & invoke
literal.RunJavaScript("jsFoo", "testparam");
Ha lo stesso effetto, ma è più facile da leggere (se hai intenzione di fare più JavaScript ;-)).
Un'altra opzione, se ti piacciono le espressioni Lambda e non ti piace specificare il nome della funzione come stringa ogni volta che la chiami, puoi fare:
var jsFoo = ScriptExtension.CreateJavaScript(
@"function jsFoo(x) { ... }");
ScriptExtension.RunJavaScript(() => jsFoo, "testparam");
purché tu abbia aggiunto la funzione di aiuto
public static object RunJavaScript(Expression<Func<LINQPad.Controls.Literal>> expr,
params object[] p)
{
LINQPad.Controls.Literal exprValue = expr.Compile()();
string jsFunction = ((MemberExpression)expr.Body).Member.Name;
return exprValue.Dump().HtmlElement.InvokeScript(true, jsFunction, p);
}
alla classe ScriptExtension
. Questo risolverà il nome della variabile che hai usato (qui jsFoo
) che sembra avere lo stesso nome della funzione JavaScript stessa (Nota come viene utilizzata l'espressione lambda per risolvere il nome della variabile, ciò non può essere fatto usando nameof(paramName)
all'interno della funzione).
A volte è utile sovrascrivere il testo scaricato invece di inserirlo in una nuova riga, ad esempio se si sta eseguendo una query di lunga durata e si desidera mostrarne l'avanzamento, ecc. (Vedere anche ProgressBar di seguito). Questo può essere fatto usando a DumpContainer
, puoi usarlo come mostrato in
Esempio 1:
void Main()
{
var dc = new DumpContainer("Doing something ... ").Dump("Some Action");
System.Threading.Thread.Sleep(3000); // wait 3 seconds
dc.Content += "Done.";
}
Si noti che per alcuni oggetti più complessi, potrebbe essere necessario utilizzare dc.UpdateContent(obj);
anziché dc.Content=...
.
Esempio 2:
void Main()
{
var dc = new DumpContainer().Dump("Some Action");
for (int i = 10; i >= 0; i--)
{
dc.UpdateContent($"Countdown: {i}");
System.Threading.Thread.Sleep(250);
};
dc.UpdateContent("Ready for take off!");
}
La visualizzazione dell'avanzamento può essere eseguita anche utilizzando ProgressBar come segue:
Esempio:
void Main()
{
var prog = new Util.ProgressBar("Processing").Dump();
for (int i = 0; i < 101; i++)
{
Thread.Sleep(50); prog.Percent = i;
}
prog.Caption = "Done";
}
Questo è simile all'esempio di dump precedente, ma questa volta mostra una bella animazione con barra di avanzamento.
Sapevi che puoi scrivere unit test in LinqPad? Ad esempio, è possibile utilizzare il framework xUnit. È disponibile tramite il supporto NUGET di LinqPad - tramite F4- nella finestra di dialogo Add NUGET..... Ecco una descrizione dettagliata su come usare xUnit con LinqPad V5 o V6.
Se ne scopro di più, aggiornerò questa risposta