Ben*_*sen 133 .net c# entity-framework linqpad linq-to-sql
有没有人有完整的LINQPad扩展方法和方法列表,例如
.Dump()
SubmitChanges()
Joe*_*ari 237
LINQPad定义了两种扩展方法(在LINQPad.Extensions中),即Dump()和Disassemble().Dump()使用LINQPad的输出格式化程序写入输出窗口并重载以允许您指定标题:
typeof (int).Assembly.Dump ();
typeof (int).Assembly.Dump ("mscorlib");
您还可以指定最大递归深度以覆盖默认的5个级别:
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()反汇编任何方法IL,以字符串形式返回输出:
typeof (Uri).GetMethod ("GetHashCode").Disassemble().Dump();
除了这两个扩展方法之外,LINQPad.Util中还有一些有用的静态方法.这些记录在自动完成中,包括:
LINQPad还提供HyperLinq类.这有两个目的:第一个是显示普通的超链接:
new Hyperlinq ("www.linqpad.net").Dump();
new Hyperlinq ("www.linqpad.net", "Web site").Dump();
new Hyperlinq ("mailto:user@domain.com", "Email").Dump();
你可以将它与Util.HorizontalRun:
Util.HorizontalRun (true,
  "Check out",
   new Hyperlinq ("http://stackoverflow.com", "this site"),
  "for answers to programming questions.").Dump();
结果:
查看此站点以获取编程问题的答案.
HyperLinq的第二个目的是动态构建查询:
// 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();
您也可以在LINQPad中编写自己的扩展方法.转到"我的查询",然后单击名为"我的扩展"的查询.所有查询都可以访问此处定义的任何类型/方法:
void Main()
{
  "hello".Pascal().Dump();  
}
public static class MyExtensions
{
  public static string Pascal (this string s)
  {
    return char.ToLower (s[0]) + s.Substring(1);
  }
}
在4.46(.02)中引入了新的类和方法:
此外,Hyperlinq类现在支持单击链接时将调用的Action委托,允许您在代码中对其作出反应,而不仅仅是链接到外部网页.
DumpContainer 是一个类,它将一个块添加到输出窗口中,可以替换其内容.
注意!记得.Dump()在DumpContainer在适当的位置本身.
使用:
var dc = new DumpContainer();
dc.Content = "Test";
// further down in the code
dc.Content = "Another test";
OnDemand是一种扩展方法,它不会将其参数的内容输出到输出窗口,而是添加一个可单击的链接,单击该链接时将链接替换.Dump()为参数的ed内容.这对于有时需要的数据结构非常有用,这些数据结构成本高昂或占用大量空间.
注意!记住在适当的地方.Dump()打电话的结果OnDemand.
要使用它:
Customers.OnDemand("Customers").Dump(); // description is optional
Util.ProgressBar 是一个可以在输出窗口中显示图形进度条的类,可以在代码移动时更改.
注意!请记住.Dump()适当位置的Util.ProgressBar对象.
要使用它:
var pb = new Util.ProgressBar("Analyzing data");
pb.Dump();
for (int index = 0; index <= 100; index++)
{
    pb.Percent = index;
    Thread.Sleep(100);
}
Mat*_*att 124
Besides the well-known myQuery.Dump("Query result:"), another feature to mention is the Util class: It contains many quite handy methods (some of them I've mentioned, but there are a lot more).
Also interesting is that you can easily modify the way Dump() works. 
Finally I'll show you how you can make changes permanent (i.e. insert, update, delete LINQ queries) using SubmitChanges() or SaveChanges() as well as how you can access the internal connection object of LinqPad.
And to round it up, I'll show you how you can create simple 2d graphic inside of LinqPad (drawing lines, bitmaps or functions).
所以,这里有一系列内置的LinqPad功能(根据我自己的工具经验):
(LinqPad v5.03.08及更高版本中提供的参数)
所有LinqPad用户都知道并喜欢复杂的.Dump()扩展方法,它可以消耗和打印(几乎)所有内容.
但是你知道有几个参数可用吗?看一下这段代码:
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
在第一示例仅打印变量a和c与生皮b和d,所述第二例子则正好相反(注意,仅指定可用的参数的2).变量y并z不能单独隐藏,因为它们不在顶层.
The following parameters are available (all are optional):
description [string] - provides a description for the object to dumpdepth [int?] - limits how deep the objects are recursively inspectedtoDataGrid [bool] - if true, the output is formatted as a datagrid rather than as RichTextexclude [string] - if you provide a comma-separated list of variables, they will be excluded from the output (in the example "a,c": b and d are shown, a and c are hidden)exclude [string] with "+" prefix - the prefix inverts the logic of the exclude parameter. This means, if you provide a comma-separated list of variables, all except the ones specified are hidden (in the example "+b,d": b and d are shown, all others hidden)var x=Util.ToExpando(obj, "a, c", "b, d"); x.Dump(); .OnDemand("click me").Dump(); instead of .Dump(), it will display a link you can click on to expand. Useful if you want to inspect values, e.g. Util.OnDemand("Customer-ID: " + customerObject.ID.ToString(), ()=>customerObject, false).Dump(); to always show the ID per default but reveal the details of customerObject only if you're interested in.More advanced topics about Dump can be found here.
This is not a LinqPad extension, but rather a .NET class, but since it is useful, I'll mention it anyway. You can get a lot of useful information you can use in your scripts such as :
Environment.UserDomainName.Dump();
Environment.MachineName.Dump();
Environment.UserName.Dump();
Environment.CurrentDirectory.Dump();
Environment.SystemDirectory.Dump();
NB为了获得Domain\UserName我会使用     System.Security.Principal.WindowsIdentity.GetCurrent().Name
而不是Environment.UserDomainName+@"\"+Environment.UserName.
(新:自LinqPad版本v4.45.05(测试版)以来可用)
Util.WriteCsv (Customers, @"c:\temp\customers.csv");
这会将表的内容写入CustomersCSV文件c:\temp\customers.csv.您还可以Util.WriteCsv在此处找到一个很好的示例,如何使用然后在Linqpad的结果窗口中显示CSV数据.
提示:
要获取/创建与查询位于同一目录中的CSV文件,您可以使用:
 var csvFile=Util.CurrentQueryPath.Replace(".linq", ".csv");
如果表很大,请ObjectTrackingEnabled = false;在编写CSV之前使用,以避免将其缓存在内存中.
如果要以XML格式而不是逗号分隔文件输出表,可以这样做:
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();
This example returns all elements having the attribute attr1 which contains the value "a" from an XML file which has the same name as the query and is contained in the same path. Check out this link for more code samples.
var pwd = Util.GetPassword("UserXY");
This will retrieve the password from LinqPad's built in password manager. To create & change the password, open the "Password manager" menu item in the "File" menu of LinqPad. If there is no such password saved when you run the C# code, a password dialog will open up asking you for the password and you have the choice to create and save it on the fly by checking the save password checkbox (in the example, the password for "UserXY" would be saved, and later on you can find this entry in the Password manager).
Advantages are that you can store the password in the LinqScripts you create securely, separately and encrypted in Windows' user profile (it is stored in %localappdata%\LINQPad\Passwords as a file). LinqPad uses Windows DPAPI to protect the password. 
Also, the password is stored centrally, so if you need to change it, you can do it in the menu and it immediately applies to all scripts you've created.
Notes:
If you don't want to save the password and just bring up a password dialog, you can use the 2nd parameter as follows:
var pwd = Util.GetPassword("UserXY", true);
This will uncheck the save password checkbox in the password dialog (however, the user is still able to check it and choose to save anyway).
If you require the password to be stored in a SecureString, you can use this helper function (n.b.: to get the extension method .ToSecureString() used, please follow this link at Stackoverflow - it also allows you to convert it back if needed): 
System.Security.SecureString GetPasswordSecure(string Name, bool noDefaultSave=true)
{
  return Util.GetPassword(Name, noDefaultSave).ToSecureString();
}
This method works like a command processor. You can invoke all commands you know from the Windows console.
Example 1 - dir:
Util.Cmd(@"dir C:\");
This will output the result of the directory without the need to .Dump it. Storing it in a variable has the advantage that you can use further Linq queries on it. For example:
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();
This will dump all files with file extensions ".exe" or ".dll" contained in C:\windows\system32. The /s switch is used to recurse all subdirectories and /b is used for bare output format. Note that the second parameter of the Cmd method is specified to suppress the console output in order to show only the filtered result using the Dump method.
You can see that this is more flexible than the wildcards you have with dir since you can use the full flexibility of Linq's query engine.
Example 2 - text editor:
You can open a file in Notepad like this:
var filePath=@"C:\HelloWorld.txt";
Util.Cmd(@"%systemroot%\system32\notepad.exe", filePath);
Displays images from an URL. Example:
var url = "http://chart.apis.google.com/chart?cht=p3&chd=s:Uf9a&chs=350x140&chl=January|February|March|April";
Util.Image(url).Dump();
Using Util.ProgressBar allows you to display a progress bar. You can use the following helper class:
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;
        }
    }
}
Simply use it as the following example shows:
void Main()
{
    var pb1= new ProgressBar();
    Thread.Sleep(50);
    pb1.Update(50, "Doing something"); Thread.Sleep(550);
    pb1.Update(100); Thread.Sleep(50);
}
You can alternatively use Util.Progress to update LinqPads integrated progress bar, for example:
Util.Progress = 25; // 25 percent complete
The difference is that it will not display in the results window, and you can't assign a message to it.
Displays HTML in the output window. Example:
Util.RawHtml (new XElement ("h1", "This is a big heading")).Dump();
You can use this example function
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);
}
to show hyperlinks in the result window - or any actions like opening your favourite editor. Usage:
ShowUrl("http://stackoverflow.com", "Check out StackOverflow");
Note that this function always works, while new Hyperlinq ("http://myURL", "Web site").Dump(); does not work for some kind of URLs (especially, if you have to pass port names like ":1234" as part of the URL).
Reads input from the console. Example:
int age = Util.ReadLine<int> ("Enter your age");
As a synonym for Util.ReadLine<string>(), you can use Console.ReadLine() as well.
But there is more! You can create a simple JSON parser with the following snippet - quite useful, for example if you want to parse and test a JSON string on the fly. Save the following snippet as JSONAnalyzer.linq using a text editor and then open it in LinqPad (this is to add the references easily on the fly):
<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");
}
Now you can run it and simply paste a JSON string from the clipboard into the console - it will use the Dump function to display it as an object nicely - and you also get the error messages of the parser on the screen to fix issues. Very useful for debugging AJAX.
If you need to clear the results window inside your script, use:
Util.ClearResults();
Either use it at the beginning of your script, or - if you're running multiple queries in a script - you should wait for user input before blanking the screen (e.g. by preceding it with Util.ReadLine).
Also interesting is, that you can influence the output of the .Dump() method. Simply implement the interface ICustomMemberProvider, e.g.
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
}
If you create an instance of this class, like
var obj1 = new test();
obj1.Dump("Test");
then it will output only Hint, constMember1, constMember2, and myprop, but not property xyz:

If you need to display a messagebox, look here how to do it.
For example, you can display an InputBox by using the following code
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
    }
}
(don't forget to press F4 and add Microsoft.VisualBasic.dll and its namespaces to make this work)
(new: available since LinqPad version v4.52.1 (beta))
Allows you to run another LINQPad script from within your script or within your own .NET program or Windows service (by referencing the LINQPad4-AnyCPU version of LINQPad.exe). It executes the script just as the command line tool lprun.exe would do it.
Examples:
const string path=@"C:\myScripts\LinqPad\";
var dummy=new LINQPad.QueryResultFormat(); // needed to call Util.Run
Util.Run(path+"foo.linq", dummy);
This example runs the script foo.linq, which contains the following sample code:
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");
}
It allows you to distinguish if the script was run from inside the LinqPad GUI or via lprun.exe or with Util.Run.
Note: The following variants of invocation might be helpful:
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
If you're using LinqToSQL, you might want to make changes permanent (for insert/update/delete operations).
Since the database context is implicitly made by LinqPad, you need to call  SubmitChanges() after each change as shown below.
Examples for (LinqPad-)Northwind database:
Insert
var newP = new Products() { ProductID=pID, CategoryID=cID, 
            ProductName="Salmon#"+pID.ToString() };
Products.InsertOnSubmit(newP);
SubmitChanges();    
Update
var prod=(from p in Products
            where p.ProductName.Contains("Salmon")
            select p).FirstOrDefault();
prod.ProductName="Trout#"+prod.ProductID.ToString();
SubmitChanges(); 
Delete
var itemsToDelete=Products.Where(p=> p.ProductName.Contains("Salmon") ||
    p.ProductName.Contains("Trout"));
foreach(var item in itemsToDelete) { Products.DeleteOnSubmit(item); }
SubmitChanges();
Note: In order to get valid IDs for the previous examples, you can use:
var cID = (from c in Categories 
            where c.CategoryName.Contains("Seafood") 
            select c).FirstOrDefault().CategoryID;
var pID = Products.Count()+1;
before you invoke them.
If you're using Entity Framework, you might want to make changes permanent as well (for insert/update/delete operations).
Since the database context is implicitly made by LinqPad, you need to call  SaveChanges() after each change as shown below.
The examples are basically the same as before for LinqToSQL, but you need to use SaveChanges() instead, and for inserting and deleting the methods have changed as well.
Insert
var newP = new Products() { ProductID=pID, CategoryID=cID, 
            ProductName="Salmon#"+pID.ToString() };
Products.Add(newP);
SaveChanges();  
Update
var prod=(from p in Products
            where p.ProductName.Contains("Salmon")
            select p).FirstOrDefault();
prod.ProductName="Trout#"+prod.ProductID.ToString();
SaveChanges(); 
Delete
var itemsToDelete=Products.Where(p=> p.ProductName.Contains("Salmon") ||
    p.ProductName.Contains("Trout"));
foreach(var item in itemsToDelete) { Products.Remove(item); }
SaveChanges();
Note: In order to get valid IDs for the previous examples, you can use:
var cID = (from c in Categories 
            where c.CategoryName.Contains("Seafood") 
            select c).FirstOrDefault().CategoryID;
var pID = Products.Count()+1;
before you invoke them.
In LinqPad, the database context is established automatically by using the combobox at the top and picking the right database for your query. But sometimes, it is useful to reference it explicitly, for example if you copy some code from your project out of Visual Studio, and paste it into LinqPad.
Your code snippet taken from the Visual Studio project very likely looks like this:
var prod=(from p in dc.Products
            where p.ProductName.Contains("Salmon")
            select p).FirstOrDefault();
prod.ProductName="Trout#"+prod.ProductID.ToString();
dc.SaveChanges(); 
Now what to do with dc? Of course, you could remove every occurrence of dc. in your query, but it is much easier. Just add
var dc=this; // UserQuery
to the top of your snippet like so:
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(); 
}   
and the code will work instantly!
Using LinqPad with OleDb, converting a datatable to Linq object, SQL queries in Linq
The following code snippet helps you to use LinqPad with OleDb. Add System.Data.OleDb from the System.Data assembly to the query properties, then paste the following code into 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();
Now add a SqlServer connection to LinqPad and add the Northwind database in order to run this example.
N.B.: If you just want to get the database and server of the currently selected connection, you can use this code snippet:
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();
}
You can even convert myDS into Linq, the answers to the following question show how to do it: Nice examples of using .NET 4 dynamic keyword with Linq
One more example: Suppose your DBA gives you a SQL query and you want to analyze the results in LinqPad - of course in Linq, not in SQL. Then you can do the following:
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 this example the DBA's SELECT query is just "thrown into" the command text, and the results are filtered and ordered by City.  
Of course, this is a simplified example, your DBA would probably support you with a more complex script, but you're getting the idea: Just add a supporting result class which contains all the fields from the SELECT clause and then you can directly use it. 
You can even take the result from a stored procedure this way and use it in Linq. As you can see, in this example I don't care about the data type and use dynamic to express it. 
So this is really about rapid programming to be able to analyze data quickly. You shouldn't do this in your real application for various reasons (SQL injection, because you can use EF from the beginning etc).
Draw graphic in LinqPad, part 1
To use the examples below, press F4 and add System.Windows.dll, System.Windows.Forms.dll, WindowsFormsIntegration.dll, PresentationCore.dll and PresentationFramework.dll to your LinqPad program and also add the namespace System.Windows.Shapes. 
The 1st example simply draws a line:
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");
The 2nd example shows how you can display graphic in LinqPad by using the PanelManager. Normally LinqPad only supports Wpf objects. This example  uses System.Windows.Forms.Integration.WindowsFormsHost to make a Windows.Forms.PictureBox available (it was inspired by this):
// 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);
}
This will create the following graphic (panel items "Graphic" and "Picture" are added by the examples above):
If you want to display the images from the Northwind database, you can do the following:
Change the image file name to "NorthwindPics.jpg", then add the following code at the beginning of the 2nd example's Main() method:
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();
}
It will read the first record from the Employees table and display the picture.
Check out the following links to find out more: 
Shapes and basic drawing in WPF 
LinqPad custom visualizers
Note: You can achieve the same without the PanelManager as well, as the following example, which I saw here shows:
// 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();
}
It is using the .Dump() command to display it. You can invoke image.Dump() multiple times and it will append the image.
Draw graphic in LinqPad, part 2
The following example, inspired by this post, is showing how to implement a simple function plotter in Linqpad 5 using 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;
}
It is using the capability of LinqPad to display Windows forms in the results panel. 
  
 
Add references (press F4):
 System.Drawing.dll, System.Windows.Forms.dll, System.Windows.Forms.DataVisualization.dll 
and add all namespaces from these assemblies.
Additional hints/further reading:
Want to use LinqPad in Visual Studio? Here's how you can do that.
Need to have LinqPad as a "Portable app"? Read here how to do that.
Joe's website for LinqPad is always an excellent source. Inside LinqPad, Help -> What's New gives you hints about new functions and methods. The LinqPad Forum also contains helpful hints.
Also very helpful: This article about Linq(Pad) debugging.
Use lprun.exe for running LINQ queries in your <
在我之前的回答中达到了StackOverflow 文本限制,但 LinqPad 中还有更多很酷的扩展。其中一些我想提一下:
列表
您知道吗,您可以在 LinqPad 中编写自己的扩展,可用于所有查询?您可以这样做:在 LinqPad 中,转到左侧的“我的查询”选项卡,向下滚动到最后,直到看到“我的扩展”。双击它,它将打开一个名为 My Extensions 的特殊查询窗口。您在那里写的内容将在所有查询中可用。
现在将以下代码粘贴到其中,然后使用Ctrl+保存S:
我的扩展
void Main()
{
    // no code here, but Main() must exist
}
public static class MyExtensions
{
    /// <summary>
    /// This will list the tables of the connected database
    /// </summary>
    public static void ListTables(this System.Data.Linq.DataContext dc)
    {
        var query = dc.Mapping.GetTables();
        query.Select(t => t.TableName).OrderBy(o => o).Dump();
    }
}
Joe(LinqPad 的作者)好心地为我提供了这个片段 - 它展示了如何将数据上下文传递给我的扩展。
按以下方式使用此扩展:在 LinqPad 中打开一个新的 C# 查询窗口(使用Ctrl+ N),然后连接到您选择的数据库,并键入:
新查询
void Main()
{
    this.ListTables();
}
重要提示:如果您未连接到数据库,则扩展不可用并且 LinqPad 将显示错误。因此,首先连接到数据库,然后键入this.ListTables();.
请注意,IntelliSense 将显示我们在我的扩展中键入的 XML 注释的摘要。运行后,您将获得当前数据库的表列表。
之前我已经展示了如何使用 MyExtensions。现在,如果您想要一个全局 appsettings.json 文件或每个脚本一个,您可以使用以下扩展名:
public static class MyExtensions
{
    // needs: Microsoft.Extensions.Configuration.json, press F4 and add it as NUGET package
    public static IConfiguration AppSettings(string path = null)
    {
            IConfiguration config = null;
            var configFile = (path != null) ? path : Util.CurrentQueryPath.Replace(".linq", ".appsettings.json");
            if (System.IO.File.Exists(configFile))
            {
                var builder = new ConfigurationBuilder().AddJsonFile(configFile);
                config = builder.Build();
            }
            else
            {
                configFile.Dump("Not found");
            }
            return config;
    }
}
您也可以将它直接存储在您的 C# 程序中,但这种方式默认可用,您只需加载一次 NUGET。
假设您编写了一个 LinqPad 程序"YourCSharpProgram.linq"。现在您可以提供类似的配置
var config1 = MyExtensions.AppSettings();
或喜欢
var config2 = MyExtensions.AppSettings("C:\MyGlobalSettings\appsettings.json");
第一个选项 config1 将期望文件下方的设置"YourCSharpProgram.linq"并附"appsettings.json"加到它,这意味着您的设置必须"YourCSharpProgram.linq.appsettings.json"与程序位于同一文件夹中。第二个选项仅使用指定的绝对路径。
如果您的设置文件包含
{
    "AzureStorage": {
        "StorageConnectionString": "some connection string"
    }
}
你可以像这样访问它
var config = MyExtensions.AppSettings();
string connectionString = config.GetSection("AzureStorage").GetSection("StorageConnectionString").Value.ToString();
connectionString.Dump();
注意:使用配置的第二种方法是将 JSON 文件的绝对路径放置在 LinqPads F4 对话框中。在 LinqPad 5 中,这更好,因为设置文件有一个单独的选项卡(在那里AppConfig,因为版本 5 适用于 .NET,而不适用于 .NET core)。您必须像使用程序集一样引用它,这并不明显。所以我更喜欢上面描述的。
.Dump())从LinqPad 的5.42 测试版开始,您可以嵌入 JavaScript 函数并直接从您的 C# 代码中调用它们。尽管这有一些限制(与 JSFiddle 相比),但它是在 LinqPad 中快速测试一些 JavaScript 代码的好方法。
例子:
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");
}
在本例中,jsFoo准备了一个带有一个参数的函数并将其存储在变量 中literal。然后,它通过.Dump().HtmlElement.InvokeScript(...)传递参数被渲染和调用testparam。
JavaScript 函数用于external.Log(...)在 LinqPad 的输出窗口中输出文本,并alert(...)显示弹出消息。
您可以通过添加以下扩展类/方法来简化此操作:
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);
    }
}
然后你可以像下面这样调用前面的例子:
    // 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");
这具有相同的效果,但更易于阅读(如果您打算做更多的 JavaScript ;-))。
另一种选择,如果您喜欢 Lambda 表达式并且不喜欢每次调用时都将函数名称指定为字符串,则可以执行以下操作:
var jsFoo = ScriptExtension.CreateJavaScript(
            @"function jsFoo(x) { ...  }"); 
ScriptExtension.RunJavaScript(() => jsFoo, "testparam");
如果你已经添加了辅助函数
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);
}
到班级ScriptExtension。这将解析您使用的变量名称(此处jsFoo),该名称恰好与 JavaScript 函数本身的名称相同(请注意 lambda 表达式如何用于解析变量名称,这不能通过nameof(paramName)在函数内部使用来完成)。
您知道可以在 LinqPad 中编写单元测试吗?例如,您可以使用 xUnit 框架。对于 LinqPad 的第 5 版,可通过 LinqPad 的 NUGET 支持 - 通过F4- 在对话框中单击Add NUGET....。从 LinqPad 的第 6 版开始,它是内置的(菜单查询 -> 添加 XUnit 测试支持)。以下是如何在LinqPad V5 或 V6 中使用 xUnit的分步说明 。
有时覆盖您转储的文本而不是将其放入新行很有用,例如,如果您正在执行长时间运行的查询并希望显示其进度等(另请参见下面的 ProgressBar)。这可以通过使用 a 来完成DumpContainer,您可以按照如下所示使用它
示例 1:
void Main()
{
   var dc = new DumpContainer("Doing something ... ").Dump("Some Action");
   System.Threading.Thread.Sleep(3000); // wait 3 seconds
   dc.Content += "Done.";
}
请注意,对于一些更复杂的对象,您可能必须使用dc.UpdateContent(obj);而不是dc.Content=...。
示例 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!");
}
也可以使用 ProgressBar 来显示进度,如下所示:
例子:
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";
}
这类似于之前的转储示例,但这次显示了一个不错的进度条动画。
您可以使用Util.HighlightIf(condition, object)或来创建彩色转储Util.HighlightIf(condition, htmlcolor, object)。
以下示例取自 LinqPad 的发行说明,并对其进行了更多着色,展示了如何:
void Main()
{
    (from file in new DirectoryInfo(Util.LINQPadFolder).GetFiles()
    select 
        Util.HighlightIf(file.Extension == ".txt", "lightblue",
        Util.HighlightIf(file.Extension == ".json" || file.Extension == ".xml", "lightcyan",
        Util.HighlightIf(file.Extension == ".cmd" || file.Extension == ".bat", "lightyellow",
        Util.HighlightIf(file.Extension == ".dll", "lightgreen",  
        Util.HighlightIf(file.Extension == ".exe",    // Highlight the entire row if the file is an executable.
                         new {file.Name, 
                              Length=Util.HighlightIf(file.Length>999999,"orange",file.Length) ,
                              LastWriteDate=DateTime.Today.Date.ToString("yyyy-MM-dd")}
        )))))).Dump();
}
现在,它有什么作用?它基于以下颜色为单元格着色
.bat,.txt,.json,.cmd,.dll,.xml和.exe对他们每个人不同的颜色(某些共享相同的颜色)。999999 bytes,其单元格将显示为橙色。这将创建一个转储,如:
LinqPad 的付费版本(LinqPad 6 Premium)支持一个查询中的多个数据库。如果您想详细了解它是如何工作的,请参阅 StackOverflow: 
 LinqPad using multiple data contexts 中的这个答案。
如果我发现更多,我会不时更新这个答案
| 归档时间: | 
 | 
| 查看次数: | 38600 次 | 
| 最近记录: |