LINQPad [扩展]方法

是否有人拥有 LINQPad 扩展方法和方法的完整列表,例如

.Dump()


SubmitChanges()
53159 次浏览

LINQPad 定义了两个扩展方法(在 LINQPad 中)。延伸部分) ,即 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

反汇编()将任何方法反汇编为 IL,并以字符串形式返回输出:

typeof (Uri).GetMethod ("GetHashCode").Disassemble().Dump();

除了这两种扩展方法之外,LINQPad 中还有一些有用的静态方法。直到。这些都在自动完成中记录下来,包括:

  • Cmd -执行 shell 命令或外部程序
  • CreateXhtmlWriter -创建一个使用 LINQPad 的 Dump ()格式化程序的文本编写器
  • SqlOutputWriter -返回写入 SQL 输出窗口的文本编写器
  • GetMyQueries 取样-返回表示保存的查询/示例的对象集合(例如,使用 Edit | Search All 执行搜索)
  • 突出显示 -包装对象,以便在转储时突出显示黄色
  • HorizontalRun -允许在同一行上转储一系列对象

LINQPad 还提供 HyperLinq 类,它有两个用途: 第一个用途是显示普通的超链接:

new Hyperlinq ("www.linqpad.net").Dump();
new Hyperlinq ("www.linqpad.net", "Web site").Dump();
new Hyperlinq ("mailto:user@domain.example", "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) 引入了新的类和方法:

  • DumpContainer (类)
  • OnDemand (扩展方法)
  • Util. Progress sBar (类)

此外,Hyperlinq 类现在支持一个 开拍委托,当您单击该链接时将调用该委托,从而允许您以代码的形式对其作出反应,而不仅仅是链接到外部网页。

DumpContainer是一个类,它在输出窗口中添加一个块,可以替换其内容。

注意! 记住 .Dump()DumpContainer本身在适当的位置。

使用方法:

var dc = new DumpContainer();
dc.Content = "Test";
// further down in the code
dc.Content = "Another test";

OnDemand是一种扩展方法,它不会将其参数的内容输出到输出窗口,而是添加一个可单击的链接,当单击该链接时将用参数的 .Dump()ed 内容替换该链接。这对于有时需要的数据结构非常有用,因为这些数据结构成本高昂或占用大量空间。

注意! 请记住在适当的位置调用 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);
}

Dump 是一个全局扩展方法,SubmitChanges 来自作为 System 的 DataContext 对象。百科。Linq.DataContext 对象。

据我所知,LP 只添加了转储和反汇编功能。虽然我强烈建议打开它在反射器,看看还有什么其他可以使用。其中一个更有趣的东西是 LINQPad。Util 命名空间,它有一些好东西由 LINQPad 内部使用。

LinqPad 扩展方法. 2的第1部分

转到第二部分


除了众所周知的 myQuery.Dump("Query result:")之外,另一个值得一提的特性是 Util类: 它包含许多非常方便的方法(其中一些我已经提到过,但还有更多)。

同样有趣的是,你可以 修改 Dump()的工作方式

最后,我将向您展示如何使用 SubmitChanges()SaveChanges()进行 使变化永久化(即 插入,更新,删除 LINQ 查询) ,以及如何访问 LinqPad 的内部连接对象。

为了综合起来,我将向您展示如何在 LinqPad (绘制 线条,位图功能)中创建简单的 二维图形

因此,下面是 内置 LinqPad 特色的集合(来自我使用该工具的经验) :


。倾倒()

(LinqPad v5.03.08及以上版本提供的参数)

.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

第一个例子只打印变量 ac,隐藏 bd,而 第二个例子则相反(注意它只指定了2个可用参数)。变量 yz不能单独隐藏,因为它们不在顶层。

以下参数可用(都是可选的) :

  • description[ string ]-提供要转储的对象的说明
  • depth[ int? ]-限制递归检查对象的深度
  • toDataGrid[ bool ]-如果为 true,则将输出格式设置为 datagrid,而不是 RichText
  • exclude[ string ]-如果您提供一个逗号分隔的变量列表,它们将被排除在输出之外(在示例“ a,c”中,显示了 bd,隐藏了 ac)
  • 带“ +”前缀的 exclude[ string ]-前缀反转排除参数的逻辑。这意味着,如果您提供一个以逗号分隔的变量列表,那么除了指定的变量之外,所有变量都是隐藏的(在示例“ + b,d”中显示了 bd,其他变量都是隐藏的)
  • 在变量中存储包含和排除的属性(从 LinqPad V5.09.04开始) : < br/> var x=Util.ToExpando(obj, "a, c", "b, d"); x.Dump(); < br/> 第一个字符串包含要包含的属性列表,第二个字符串包含要排除的属性列表
  • 点击展开: 如果你使用 .OnDemand("click me").Dump();而不是 .Dump(),它会显示一个链接,你可以点击展开。如果您想检查值,例如 Util.OnDemand("Customer-ID: " + customerObject.ID.ToString(), ()=>customerObject, false).Dump();总是显示每个默认值的 ID,但只有在您感兴趣时才显示 customerObject的详细信息,这很有用。

关于 Dump 的更高级的主题可以在 < br/> 这里(自定义倾倒)(扩展部分第2部分)中找到。


直到,写简历

(最新消息:LinqPad 版本4.45.05(beta)起可用)

Util.WriteCsv (Customers, @"c:\temp\customers.csv");

这将把表 Customers的内容写入 CSV 文件 c:\temp\customers.csv。你也可以找到一个很好的例子来说明如何使用 Util.WriteCsv,然后在 Linqpad 的结果窗口 给你中显示 CSV 数据。

提示:

  • 要获取/创建与查询在同一目录中的 CSV 文件,可以使用:
    var csvFile=Util.CurrentQueryPath.Replace(".linq", ".csv");

  • 如果表很大,在编写 CSV 之前使用 ObjectTrackingEnabled = false;,以避免在内存中缓存它。

  • 如果希望以 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();
    

此示例返回所有具有属性 attr1的元素,该属性包含 XML 文件中的值 "a",该 XML 文件与查询具有相同的名称并包含在相同的路径中。有关更多代码示例,请查看 这个链接。


Util. 获取密码

var pwd = Util.GetPassword("UserXY");

这将从 LinqPad 内置的密码管理器中检索密码。要创建和更改密码,请在 LinqPad 的 “文件”菜单中打开 “密码管理器”菜单项。如果在运行 C # 代码时没有保存密码,那么将会打开一个密码对话框,询问您的密码,您可以选择通过选中 保存密码复选框来创建并动态保存密码(在本例中,“ UserXY”的密码将被保存,稍后您可以在 密码管理器中找到这个条目)。

优点是可以将密码存储在安全地创建的 LinqScripts 中,并在 Windows 的用户配置文件中进行单独和加密(密码作为文件存储在 %localappdata%\LINQPad\Passwords中)。LinqPad 使用 WindowsDPAPI 来保护密码。

此外,密码是集中存储的,所以如果您需要更改它,您可以在菜单中执行此操作,并且它会立即应用于您创建的所有脚本。

备注:

  • 如果你不想保存密码,只是打开一个密码对话框,你可以使用第二个参数如下:
    var pwd = Util.GetPassword("UserXY", true);
    这将取消选中密码对话框中的 保存密码复选框(但是,用户仍然可以选中它并选择保存)。

  • 如果你需要将密码存储在 SecureString中,你可以使用这个 helper 函数(n.b: 为了得到使用的扩展方法 .ToSecureString(),请按照 Stackoverflow 的这个链接-它也允许你在需要时将其转换回来) :
    System.Security.SecureString GetPasswordSecure(string Name, bool noDefaultSave=true)
    {
    return Util.GetPassword(Name, noDefaultSave) < a href = “ https://stackoverflow. com/a/38016279/1016343”> .ToSecureString();
    } < br/>


直到 CMD

此方法的工作原理类似于命令处理程序。您可以从 Windows 控制台调用已知的所有命令。

例子一-目录:

Util.Cmd(@"dir C:\");

这将输出目录的结果,而不需要 .Dump它。将它存储在一个变量中的优点是,您可以对它使用进一步的 Linq 查询。例如:

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();

这将转储所有具有文件扩展名的文件”。或。包含在 C:\windows\system32中的 dll”。/s开关用于递归所有子目录,/b用于纯输出格式。注意,指定 Cmd 方法的第二个参数是为了抑制控制台输出,以便使用 Dump 方法仅显示筛选后的结果。

您可以看到,这比使用 dir的通配符更加灵活,因为您可以充分利用 Linq 查询引擎的灵活性。

示例2-文本编辑器:

你可以像这样在记事本中打开一个文件:

var filePath=@"C:\HelloWorld.txt";
Util.Cmd(@"%systemroot%\system32\notepad.exe", filePath);

直到,图像

显示 URL 中的图像。示例:

var url = "http://chart.apis.google.com/chart?cht=p3&chd=s:Uf9a&chs=350x140&chl=January|February|March|April";
Util.Image(url).Dump();

Util 进步酒吧进步

使用 Util.ProgressBar可以显示进度条:

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;
}
}
}

简单地使用它,如下面的例子所示:

void Main()
{
var pb1= new ProgressBar();
Thread.Sleep(50);
pb1.Update(50, "Doing something"); Thread.Sleep(550);
pb1.Update(100); Thread.Sleep(50);
}

您也可以使用 Util.Progress来更新 LinqPads 集成进度条,例如:

Util.Progress = 25; // 25 percent complete

区别在于它不会显示在结果窗口中,而且您不能为它分配消息。


Util. RawHtml

在输出窗口中显示 HTML。示例:

Util.RawHtml (new XElement ("h1", "This is a big heading")).Dump();

Util 的 Hyperlinq

您可以使用这个示例函数

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);
}

在结果窗口中显示超链接-或者任何动作,比如打开你喜欢的编辑器。 用法:

ShowUrl("http://stackoverflow.com", "Check out StackOverflow");

注意 ,这个函数总是可以工作的,而 new Hyperlinq ("http://myURL", "Web site").Dump();对某些类型的 URL 不起作用(特别是,如果您必须将“ : 1234”这样的端口名作为 URL 的一部分传递)。


Util ReadLine

从控制台读取输入。例如:

int age = Util.ReadLine<int> ("Enter your age");

作为 Util.ReadLine<string>()的同义词,也可以使用 Console.ReadLine()

但还有更多!您可以使用以下代码片段创建一个 简单的 JSON 解析器-非常有用,例如,如果您想要动态地解析和测试一个 JSON 字符串。然后在 LinqPad 中打开它(这是为了方便地动态添加引用) :

<Query Kind="Program">
<Reference>&lt;RuntimeDirectory&gt;\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");
}

现在您可以运行它,并简单地从剪贴板粘贴一个 JSON 字符串到控制台-它将使用 Dump函数很好地显示它作为一个对象-您还可以在屏幕上获得解析器的错误消息来修复问题。对于调试 AJAX 非常有用。

JSON


直到结果出来

如果需要清除脚本中的结果窗口,请使用:

Util.ClearResults();

要么在脚本的顶部使用它,要么——如果在一个脚本中运行多个查询——在屏幕空白之前应该等待用户输入(例如,在输入之前使用 Util.ReadLine)。


Custom.Dump ()-ICustomMemberProvider

同样有趣的是,您可以更改 .Dump()方法的输出。

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
}

如果创建此类的实例,如

var obj1 = new test();
obj1.Dump("Test");

那么它将只输出 HintconstMember1constMember2myprop,而不输出属性 xyz:

Linqpad dump


在 LinqPad 中显示消息框或 InputBox

如果需要显示消息框,请查看 给你如何做到这一点。

例如,可以使用以下代码显示 InputBox

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
}
}

(不要忘记按下 F4键并添加 Microsoft. VisualBasic.dll 及其名称空间来完成这项工作)


Util 快跑

(最新消息:LinqPad 版本4.52.1(beta)起可用)

允许您在自己的脚本内或自己的脚本内运行另一个 LINQPad 脚本。NET 程序或 Windows 服务(通过引用 LINQPad.exe的 LINQPad4-AnyCPU 版本)。它像命令行工具 lprun.exe那样执行脚本。

例子:

const string path=@"C:\myScripts\LinqPad\";
var dummy=new LINQPad.QueryResultFormat(); // needed to call Util.Run
Util.Run(path+"foo.linq", dummy);

此示例运行脚本 foo.linq,其中包含以下示例代码:

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");
}

它允许您检查脚本是从 LinqPad GUI 内部运行的,还是通过 lprun.exe或使用 Util.Run运行的。

注意: 以下调用的变体可能会有所帮助:

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

SubmitChanges ()-Linq To SQL

如果您正在使用 LinqToSQL,那么您可能希望使更改永久化(对于 插入/更新/删除操作)。 由于数据库上下文是由 LinqPad 隐式创建的,因此在每次更改后都需要调用 SubmitChanges(),如下所示。

北风数据库示例:

插入

var newP = new Products() { ProductID=pID, CategoryID=cID,
ProductName="Salmon#"+pID.ToString() };
Products.InsertOnSubmit(newP);
SubmitChanges();

更新

var prod=(from p in Products
where p.ProductName.Contains("Salmon")
select p).FirstOrDefault();
prod.ProductName="Trout#"+prod.ProductID.ToString();
SubmitChanges();

删除

var itemsToDelete=Products.Where(p=> p.ProductName.Contains("Salmon") ||
p.ProductName.Contains("Trout"));
foreach(var item in itemsToDelete) { Products.DeleteOnSubmit(item); }
SubmitChanges();

注意: 为了获得前面示例的有效 ID,您可以使用:

var cID = (from c in Categories
where c.CategoryName.Contains("Seafood")
select c).FirstOrDefault().CategoryID;


var pID = Products.Count()+1;

在你启动它们之前。


SaveChanges ()-实体框架

如果您正在使用 实体架构,那么您可能也希望使更改永久化(对于 插入/更新/删除操作)。 由于数据库上下文是由 LinqPad 隐式创建的,因此在每次更改后都需要调用 SaveChanges(),如下所示。

对于 LinqToSQL,这些示例基本上与以前相同,但是您需要使用 SaveChanges(),并且对于插入和删除方法也已经更改。

插入

var newP = new Products() { ProductID=pID, CategoryID=cID,
ProductName="Salmon#"+pID.ToString() };
Products.Add(newP);
SaveChanges();

更新

var prod=(from p in Products
where p.ProductName.Contains("Salmon")
select p).FirstOrDefault();
prod.ProductName="Trout#"+prod.ProductID.ToString();
SaveChanges();

删除

var itemsToDelete=Products.Where(p=> p.ProductName.Contains("Salmon") ||
p.ProductName.Contains("Trout"));
foreach(var item in itemsToDelete) { Products.Remove(item); }
SaveChanges();

注意: 为了获得前面示例的有效 ID,您可以使用:

var cID = (from c in Categories
where c.CategoryName.Contains("Seafood")
select c).FirstOrDefault().CategoryID;


var pID = Products.Count()+1;

在你启动它们之前。

如果你需要交易,看看这篇文章: 如何嵌套事务


This-database 上下文

LinqPad中,通过使用顶部的组合框并为查询选择正确的数据库,自动应用 数据库上下文。 但是有时,明确地引用它是有用的,例如,如果您从 视觉工作室中复制项目中的某些代码,并将其粘贴到 LinqPad 中。

从 VisualStudio 项目获取的代码片段很可能如下所示:

var prod=(from p in dc.Products
where p.ProductName.Contains("Salmon")
select p).FirstOrDefault();
prod.ProductName="Trout#"+prod.ProductID.ToString();
dc.SaveChanges();

现在如何处理 dc?当然,您可以删除查询中出现的每个 dc.,但是这要容易得多。 只要像这样将它添加到代码片段的顶部:

UserQuery dc { get => this; }
void Main()
{
var prod=(from p in dc.Products
where p.ProductName.Contains("Salmon")
select p).FirstOrDefault();
prod.ProductName="Trout#"+prod.ProductID.ToString();
dc.SaveChanges();
}

代码马上就可以工作了!


这个,连接

在 OleDb 中使用 LinqPad,将数据表转换为 Linq 对象,在 Linq 中执行 SQL 查询

下面的代码片段帮助您在 OleDb 中使用 LinqPad。将 System.Data程序集中的 System.Data.OleDb添加到查询属性中,然后将以下代码粘贴到 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();

现在将 SqlServer 连接添加到 LinqPad,并添加 Northwind 数据库以运行此示例。

注意: 如果只想获取当前选定连接的数据库和服务器,可以使用下面的代码片段:

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();
}

你甚至可以把 myDS转换成 林克,,下面这个问题的答案告诉你怎么做: 在 Linq 中使用.NET4动态关键字的好例子

再举一个例子: 假设你的数据库管理员给你一个 SQL 查询,你想在 LinqPad 分析结果——当然是在 Linq,而不是 SQL。你可以这样做:

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;
}

在这个示例中,DBA 的 SELECT 查询被“抛入”命令文本中,结果由 City 进行筛选和排序。
当然,这是一个简化的例子,您的 DBA 可能会给您一个更复杂的脚本,但是您已经得到了这样的想法: 添加一个支持的结果类,其中包含来自 SELECT 子句的所有字段,然后您可以直接使用它。
您甚至可以以这种方式从存储过程获取结果并在 Linq 中使用它。正如您所看到的,在这个示例中,我不关心数据类型,而是使用 dynamic来表示它。
因此,这实际上是关于快速编程,以便能够快速分析数据。由于各种原因(SQL 注入,因为您可以从一开始就使用 EF 等) ,您不应该在您的实际应用程序中这样做。


小组经理

在 LinqPad 画图,第一部分

要使用下面的示例,请按 F4并将 System.Windows.dllSystem.Windows.Forms.dllWindowsFormsIntegration.dllPresentationCore.dllPresentationFramework.dll添加到 LinqPad 程序中,还要添加名称空间 System.Windows.Shapes

第一个例子只是画了一条线:

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");

第二个例子展示了如何使用 PanelManager 在 LinqPad 中显示图形。通常 LinqPad 只支持 Wpf 对象。这个例子使用 System.Windows.Forms.Integration.WindowsFormsHost使得 PictureBox可用(它的灵感来自于 这个) :

// 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);
}

这将创建以下图形(面板项目“图形”和“图片”是由上面的例子添加) :

Showing_Graphic_in_LinqPad

如果你想要 显示 Northwind 数据库中的图像,,你可以做到以下几点:
将图像文件名更改为“ NorthwindPics.jpg”,然后在 第二个例子 Main ()方法的开头添加以下代码:

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();
}

它将读取“雇员”表中的第一条记录并显示图片。

以下连结载有更多相关资料:
WPF 中的形状和基本绘图
LinqPad 自定义可视化工具

注意: 您也可以在不使用 PanelManager 的情况下实现相同的功能,如下面的示例所示,我看到 给你所示:

// 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();
}

它使用 .Dump()命令来显示它。您可以多次调用 image.Dump(),它将追加映像。


Windows 窗体

在 LinqPad 中绘制图形,第2部分

下面的例子受到了 翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳 post 的启发,展示了如何在 Linqpad 使用 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;
}

它使用 LinqPad 的功能在结果面板中显示 Windows 表单。 < br/> < img src = “ https://i.stack.imgur.com/7f0DC.png”alt = “ example”/> < img src = “ https://i.stack.imgur.com/7f0DC.png”alt = “ example”/>
添加 参考文献(按 F4): < br/> System.Drawing.dllSystem.Windows.Forms.dllSystem.Windows.Forms.DataVisualization.dll < br/> 并添加来自这些程序集的所有名称空间。


额外提示/进一步阅读:

  • 想在 视觉工作室中使用 LinqPad 吗。

  • 需要有 LinqPad 作为一个 “便携式应用程序”? 看这里如何做到这一点。

  • 乔的 LinqPad网站是一个很好的来源。在 LinqPad 内部,Help -> What's New为您提供有关新函数和方法的提示。LinqPad 论坛还包含有用的提示。

  • 也很有帮助: 这个关于 Linq (Pad)调试的文章。

  • 使用 lprun.exe运行 LINQ 查询在您的 批处理脚本。阅读 这篇文章的更多细节。 例如:
    echo Customers.Take(100) > script.txt
    lprun -lang=e -cxname=CompanyServer.CustomerDb script.txt
    在本例中,查询是一个简单的 LINQ 表达式。当然,您可以准备复杂的查询,也可以使用 -lang=program来激活程序模式。

  • 您可以在 LinqPad 左侧的 我的疑问选项卡中编写和存储扩展方法: 树的最后一个项目名为 我的分机; 双击它可以打开一个文件,在这个文件中您可以编写可用于所有查询的扩展。将它们放到公共静态类 MyExtensions中,并使用 Main()方法包含扩展的测试。


继续..。

LinqPad 扩展方法. 第2部分

转到第一部分


在我的 abc1中已经达到了30000个字符的 StackOverflow 文本限制,但是在 LinqPad 仍然有更多很酷的扩展。我想提到其中的一些:


自动滚动和其他快捷方式

  • 当查询运行 < br/> (使用 .Dump()语句)时,自动滚动 结果窗口的末尾: < br/> 按 ABC1 + ABC2 + E切换(打开或关闭)

  • 多个入口点: 按 ABC3 + ABC4 + 1运行 Main1(),按 Main2()0运行 Main2(),以此类推。
    Main2()1,您仍然需要 void Main()作为主入口点,上面的方法是额外的(可选的)入口点。

  • 运行 xUnit 测试: < br/> 按 ABC2 + ABC3 + T运行使用 [Fact][Theory] < br/> 修饰的 所有 xUnit 测试(作为准备,您需要通过 Query-> Add xUnit test support 查询-> 添加 xUnit 测试支持菜单添加对 xUnit 的支持)


环境

这不是一个 LinqPad 扩展,而是一个.NET 类,但是由于它很有用,我还是要提到它。 您可以在脚本中获得许多有用的信息,例如:

Environment.UserDomainName.Dump();
Environment.MachineName.Dump();
Environment.UserName.Dump();
Environment.CurrentDirectory.Dump();
Environment.SystemDirectory.Dump();

要获得 Domain\UserName,我会使用 System.Security.Principal.WindowsIdentity.GetCurrent().Name
而不是 Environment.UserDomainName+@"\"+Environment.UserName


在 LinqPad 中编写自己的扩展

列表

你知道你可以在 LinqPad 编写自己的扩展吗? 你可以这样做: 在 LinqPad 中,转到左侧的“ MyQuery”选项卡,向下滚动到结尾,直到看到“ MyExtended”。双击它,它将打开一个特殊的查询窗口名为我的扩展。您在那里编写的内容将在所有查询中可用。

现在把下面的代码粘贴进去,然后用 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 IOrderedEnumerable<string> ListTables(
this System.Data.Linq.DataContext dc, bool dumpIt = true)
{
var query = dc.Mapping.GetTables();
var result = query.Select(t => t.TableName).OrderBy(o => o);
if (dumpIt) result.Dump();
return result;
}
}

Joe (LinqPad 的作者)友好地向我提供了这个片段——它展示了如何将数据上下文传递给 My Extended。
注意: 对于 LinqPad 6或更高版本,您需要按 F4查询属性并勾选“ Reference LINQ-to-SQL Assembly”以使其工作。

使用此扩展的方式如下: 在 LinqPad 中打开一个新的 C # 查询窗口(使用 Ctrl + N) ,然后连接到您选择的数据库,并键入:

新问题

void Main()
{
this.ListTables();
}

重要提示: 如果您没有连接到数据库,那么扩展名不可用,LinqPad 将显示一个错误。因此,首先连接到数据库,然后键入 this.ListTables();

注意,IntelliSense 将显示我们在 MyExtended 中键入的 XML 注释的摘要。运行它之后,您将获得当前数据库的表列表。


LinqPad 中的配置文件(appsetings.json)


之前我已经演示了如何使用 MyExtended。现在,如果您想要一个全局 appsetings.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 核心)。你必须像对待程序集一样引用它,而这并不明显。所以我更喜欢上面所描述的。


。转储()-重访

单击操作的扩展

如果可以单击按钮对特定行执行操作,那么这种方法有时是有用的。 您可以通过编写一个扩展(您可以像前面描述的那样将其存储在“ MyExtended”中)来实现这一点。

Example for click column

下面的所有方法都需要位于静态的非嵌套扩展类(例如 public static class Ext { ... })中。 首先,我们需要一个操作按钮; 为了简单地创建一个按钮,我们使用了这个 helper 方法:

public static LINQPad.Controls.Button ActionButton<TSource>(this TSource arg,
string text, System.Action<TSource> selector)
=> new LINQPad.Controls.Button(text,
(LINQPad.Controls.Button b) => { selector(arg); });
    

该函数采用源类型,并允许创建一个标有文本和选择器的 Button (我们将在一分钟后看到它是什么)。

这样,我们就可以定义 DumpAction 方法如下:

public static void DumpAction<T>(this IEnumerable<T> lst, Action<T> selector,
string description = "", string clickText = "Click me")
{
lst.Select(val => new
{
val, click = val.ActionButton<T>(clickText, selector)
}).Dump(description);
}

这将追加一个列,其中包含可单击的按钮。 你可以这样使用:

// list to display
var myList = new List<string>()
{
"Apple", "Pie"
};

你要做的就是:

myList.DumpAction((x) => myAction(x), "Click Extension");

它将执行与. Dump ()方法相同的操作。 现在只需要定义一个被调用的方法 myAction:

void myAction(string payload)
{
payload.Dump("myAction");
}

如果单击将列表项的字符串值传递给该按钮,则将调用此方法。

注意: 可以对 Dictionary 进行同样的处理,上面的扩展已经可以对它们进行处理,但是它占用了大量的空间 在每一行的结果窗口中-为了解决这个问题,你可以定义第二个扩展方法:

public static void DumpActionDict<K, V>(this IEnumerable<KeyValuePair<K, V>> lst,
Action<K> selector,
string description = "", string clickText = "Click me")
                    

{
lst.Select(val => new
{
val.Key, val.Value, click = val.Key.ActionButton<K>(clickText, selector)
}).Dump(description);
}

像这样使用:

var myDict = new Dictionary<string, string>()
{
["a"] = "x",
["b"] = "y"
};


myDict.DumpActionDict((x) => myAction(x), "Extension for dict");

注意: 也可以对按钮内部的文本进行不同的格式化,看看这个例子:

public static LINQPad.Controls.Button ActionButton<TSource>(this TSource arg, string text,
System.Action<TSource> selector)
{
var btn = new LINQPad.Controls.Button(onClick: (LINQPad.Controls.Button b) => { selector(arg); });
btn.HtmlElement.InnerHtml = $"<small>{text}</small>";
return btn;
}

这将使按钮文本更小。您可以使用任何 HTML 元素。


用 Util 给你的垃圾堆上色

可以使用 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,则其单元格为橙色。

这将创建一个转储,类似于:

colordump


内联更新消息

有时,它对于转储的 覆盖文字而不是将其放入新行是有用的,例如,如果您正在执行一个长时间运行的查询,并希望显示其进度等(请参见下面的 ProgressBar)。这可以通过使用 DumpContainer来完成,您可以使用它,如

例子一:

void Main()
{
var dc = new DumpContainer("Doing something ... ").Dump("Some Action");
System.Threading.Thread.Sleep(3000); // wait 3 seconds
dc.Content += "Done.";
}

DumpContainerAnimation

注意 ,对于一些更复杂的对象,可能必须使用 dc.UpdateContent(obj);而不是 dc.Content=...

例二:

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!");
}

显示进度-Util

也可以通过使用如下进度条来显示进展情况:

例如:

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";
}

这与前面的转储示例类似,但是这次显示了一个很好的进度条动画。

enter image description here


JavaScript 函数(使用 .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");

前提是您已经添加了 helper 函数

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)来完成)。


XUnit-使用 LinqPad 进行单元测试

你知道你可以在 LinqPad 编写单元测试吗?例如,可以使用 xUnit 框架。对于 LinqPad 的版本5,可以通过 LinqPad 的 NUGET 支持——通过 F4——在对话框中单击 Add NUGET....。而且自从 LinqPad 的版本6以来,它是内置的(Menu Query-> Add XUnit test support)。下面是如何 在 LinqPad V5、 V6或 V7中使用 xUnit。

例子一:

[Fact] void TestDb1()
{
var ctx = this; // "this" represents the database context
Assert.True(ctx.Categories.Any(), "No categories");
string.Join(", ", ctx.Categories.Select(s => s.CategoryName).ToList()).Dump("Categories");
Assert.True(ctx.Products.Any(), "No Products");
string.Join(", ", ctx.Products.Select(s => s.ProductName).ToList()).Dump("Products");
}

这个示例需要一个 北风示例数据库(设置为 Linq to SQL 或者 Entity Framework Core Connection) ,分配给查询,并添加 XUnit Test 支持(选择 Query-> Add XUnit Test support in LinqPad)。它将打印所有类别和产品的结果窗口。如果数据库中没有类别或产品,则测试失败。

例二:

// for MemberData
public static IEnumerable<object[]> GetNumbers()
{
yield return new object[] { 5, 1, 3, 9 };  // 1st row: a, b, c, sum (succeeds)
yield return new object[] { 7, 0, 5, 13 }; // 2nd row: a, b, c, sum (fails)
}


[Theory]
[MemberData(nameof(GetNumbers))] // easier to handle than [ClassData(typeof(MyClass))]
void Test_Xunit(int a, int b, int c, int expectedSum)
=> Assert.Equal (expectedSum, a + b + c);

此示例使用带有成员函数 GetNumbers()[Theory]来填充参数 a, b, cexpectedSum,并且比 [Fact]具有更大的灵活性。[Fact]不能有任何参数。如果期望的和不等于 a + b + c 的和,则测试失败。这是第2行的情况: 断言将输出: (a: 7, b: 0, c: 5, expectedSum: 13)

注意: 您还可以多次使用 InlineData (例如 [InlineData(1,2,3,6)])来实现直接传递值的理论,甚至可以将其与 MemberData 属性组合使用。它将向测试添加所有值并执行它。


多数据库支持

LinqPad 的付费版本(LinqPad 6 Premium)支持查询中的多个数据库。

下面我将描述如果选择“ Linq to SQL (Optimized for SQL Server)”将获得的数据库属性的步骤。

要么创建新连接,要么打开现有连接。打开 数据库属性,选择 数据库(不要使用“ Display all in a TreeView”)

database properties

然后勾选“包括其他数据库”-这将打开另一个对话框,在那里您可以添加多个数据库:

additional databases

单击 Pick from List...,可以选择 + 选择另一个数据库。完成后,单击 Close关闭附加对话框,然后单击 Ok关闭数据库属性。

选择的数据库有“辅助”上下文(在“ this”UserQuery 中用数据库名称列出) ,第一个数据库(在“指定新数据库或现有数据库”下选择)是“主”上下文(这意味着,表直接出现在“ this”UserQuery 中)。

在连接窗口中,这将显示为

“ . MyInstance AdventureWorks2017 + AdventureWorks2017 + Northwind”


在下面的代码中,我使用“ AdventureWorks2017”作为 主要背景,“ AdventureWorks2017”和“ Northwind”作为 次要背景。

有了这样的准备,你可以做到:

public UserQuery ctx => this; // context
void Main()
{
// "primary database"
ctx.Products.Select(s => new {s.ProductID, Name=s.Name}).Take(3).Dump("AdventureWorks");


// "secondary" databases
var aw = ctx.AdventureWorks2017;
var nw = ctx.Northwind;


nw.Products.Select(s => new {s.ProductID, Name=s.ProductName}).Take(3).Dump("Northwind");
aw.Products.Select(s => new {s.ProductID, Name=s.Name}).Take(3).Dump("AdventureWorks");
}

本例中使用的两个示例数据库都来自 Microsoft,可以免费下载,并且它们都有一个 Products表,但是具有不同的属性/字段: 您可以看到我已经重命名了 ProductName/Name,所以它在所有查询中都显示为 Name。

程序会给你结果:

result

下载链接: AdventureWorks 北风,< a href = “ https://www.LinqPad.net/”rel = “ norefrer”> LinqPad