<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_快速代码生成+基础框架</title><subtitle type="text">一个普通程序员和一个优秀程序员的区别，不在于他们懂得多少，而在于他们能否与人交流思想。</subtitle><id>http://feed.cnblogs.com/blog/u/20601/rss</id><updated>2012-01-06T01:17:14Z</updated><author><name>James Li</name><uri>http://www.cnblogs.com/JamesLi2015/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/JamesLi2015/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/20601/rss"/><entry><id>http://www.cnblogs.com/JamesLi2015/archive/2012/01/06/2313920.html</id><title type="text">.NET 应用程序界面开发经验总结 设计良好的程序的表现之一就是细节做的还可以</title><summary type="text">做程序主要体现的是细节，细节方面做的好，用户会觉得你的软件比较专业。良好的架构与设计模式可以使维护方便。在用户这边，要花一些心思琢磨用户的想法。有时候用户比我们的界面设计还专业，用户有很强的行业知识，他见识过的同行业的软件比我们多。下面的这几点界面设计的体会和经验，来自于用户，在这里与大家分享。 1 如果要写数据项到注册表中，最好以加密的形式保存 虽然.NET提倡的是XCOPY，但有时...</summary><published>2012-01-06T01:17:00Z</published><updated>2012-01-06T01:17:00Z</updated><author><name>James Li</name><uri>http://www.cnblogs.com/JamesLi2015/</uri></author><link rel="alternate" href="http://www.cnblogs.com/JamesLi2015/archive/2012/01/06/2313920.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/JamesLi2015/archive/2012/01/06/2313920.html"/><content type="html">&lt;p&gt;做程序主要体现的是细节，细节方面做的好，用户会觉得你的软件比较专业。良好的架构与设计模式可以使维护方便。在用户这边，要花一些心思琢磨用户的想法。有时候用户比我们的界面设计还专业，用户有很强的行业知识，他见识过的同行业的软件比我们多。下面的这几点界面设计的体会和经验，来自于用户，在这里与大家分享。    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;1 如果要写数据项到注册表中，最好以加密的形式保存&lt;/p&gt;  &lt;p&gt;虽然.NET提倡的是XCOPY，但有时还是需要写一些必要的信息到注册表中，以减少用户的配置出错的可能性。比如，自动更新功能中，需要把自动更新的网址写到注册表中。ASP.NET Web程序如果不使用默认的80端口，也推荐在安装程序时把Port写到注册表中。对于需要用户反馈的程序，一种默认方法是把用户的feedback内容发送到邮箱中，这时需要提供邮箱的注册用户名和密码，这种情况是必须要加密的。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201201/201201060917108391.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201201/201201060917105850.png" width="784" height="202" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;有时候不小心看了一下自己的注册表(regedit)内容，也是惨不忍睹，大量的程序都会写数据项到注册表中。    &lt;br /&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;2 界面划分的基本原则是信息分类，将同类的信息放在一起，集中显示。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201201/20120106091711277.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201201/201201060917122686.png" width="784" height="225" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;这是物料主档的功能的界面，先分大类，用Tabcontrol分开，基本信息，环保指令，包装规格，计划数据，附件信息。大类里面再小的类别，用GroupBox分开，比如控制点，规格。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201201/201201060917121257.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201201/201201060917126241.png" width="404" height="137" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;规格这个地方，使用了ComboBox，这个有待于商量。当选择的数据项比较多时，应当使用ComboBox，数据项比较少时，我以为用RadioButton要合适一些,这也取决于空间的大小程度。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201201/201201060917126764.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201201/201201060917127603.png" width="404" height="196" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;这个图片中有两组Item Type，上面一组是ComboBox的翻版，下面一组对文字进行了简化调整。&lt;/p&gt;  &lt;p&gt;使用ComboBox的好处是，当它的item发生变化时，界面不需要变动，而RadioButton做不到这一点，也许这是选择ComboBox的一个很好的理由。&lt;/p&gt;  &lt;p&gt;对信息分类导向的界面设计国中，菜单项的深度也应该尽量保持在三层以内，对相同的功能进行分类。请看下图&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201201/201201060917139763.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201201/201201060917132238.png" width="404" height="161" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;只用了二层，相同的功能菜单里面，还可以用分割符号分开，以增加可读性。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;3 界面中的名词选择尽量选择专业的词汇，避免通用的词汇。比如以前我做ERP系统控制面板，总会加上Managment这个词语，如Sales Management/Purchasing Management以表达销售管理,采购管理，Management这个词语应该去掉。在很多信息分类的TabControl中，通常第一个tab page的名字叫General或者上面例子中的Basic Information,或General Information，当系统中有多个这样的界面布局时，应该保持一致。比如上面的物料主档用了Basic Information，其它的地方，在基本信息的tab page中也应该用Basic Information。举例说明&lt;/p&gt;  &lt;p&gt;采购收货的界面，第一个tab page使用General Information。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201201/201201060917131125.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201201/2012010609171312.png" width="784" height="238" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;物料清单的界面，第一个tab page也使用了General Information。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201201/201201060917132488.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201201/201201060917144963.png" width="784" height="258" /&gt;&lt;/a&gt; &lt;/p&gt;            &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;4&amp;#160; 界面设计时字体的选择。    &lt;br /&gt;以我的选择，功能界面中使用Microsoft Sans Serif, 8.25pt字体。状态栏(status)和菜单(menu)使用默认的Segoe UI, 9pt。对于功能界面，除了规定程序员在设计时使用指定的字体外，还在运行时，循环遍历一下界面中的界面控件，对不是标准字体的控件予以调整。字体统一，界面才看起来整洁，美观。&lt;/p&gt;  &lt;p&gt;不推荐在控件中使用特殊的字体，尽管你可以在部署的时候把字体也拷贝到目标机器中。Crystal Report的报表中，需要使用一些特殊的字体，运行报表前应该检测字体是否存在。比如你可以把字体以嵌入的资源的方法嵌入到程序集中，如果目标机器的指定的字体不存在，可以从程序集的资源中释放字体到字体文件夹中。&lt;/p&gt;  &lt;p&gt;&amp;#160; &lt;/p&gt;  &lt;p&gt;5 对可能造成数据无法恢复的操作必须提供确认信息,提供用户放弃选择的机会。比如删除数据，退出功能时没有保存数据，耗费很长时间的MRP运算。这在开始操作前，要给用户有反悔的选择。    &lt;br /&gt;对于删除确认，有一种情况，就是对用户的设计予以认可，充分信任。比如用户在设计菜单界面时，要删除一条菜单，这时，不应该弹出确认删除的对话框。Visual Studio中删除一项MenuStripItem时，没有要我们确认删除。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201201/201201060917144930.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201201/201201060917144897.png" width="784" height="423" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;正准备Delete菜单项中的New项，Visual Studio会认可你的操作，没有要你确认之后再删除。&lt;/p&gt;  &lt;p&gt;因为这个理由，我在自定义的Menu Designer，Form Designer，Workflow Designer中都实行这个策略，充分信任用户的操作。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/JamesLi2015/aggbug/2313920.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/JamesLi2015/archive/2012/01/06/2313920.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/JamesLi2015/archive/2012/01/05/2312678.html</id><title type="text">Visual Studio 2010 开发与调试IronPython脚本 为你的ERP/MIS 应用程序添加脚本功能</title><summary type="text">时间过得真快，Visual Studio 2010推出来快两年了，.NET 4.0也逐渐普及。.NET 4里面有一项重要的功能，就是动态语言，可以在.NET代码中直接调用第三方的动态语言脚本，请参考下面的例子程序 ScriptRuntime py = Python.CreateRuntime();//Dynamic feature only works on objects typed as '...</summary><published>2012-01-05T01:25:00Z</published><updated>2012-01-05T01:25:00Z</updated><author><name>James Li</name><uri>http://www.cnblogs.com/JamesLi2015/</uri></author><link rel="alternate" href="http://www.cnblogs.com/JamesLi2015/archive/2012/01/05/2312678.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/JamesLi2015/archive/2012/01/05/2312678.html"/><content type="html">&lt;p&gt;时间过得真快，Visual Studio 2010推出来快两年了，.NET 4.0也逐渐普及。.NET 4里面有一项重要的功能，就是动态语言，可以在.NET代码中直接调用第三方的动态语言脚本，请参考下面的例子程序&lt;/p&gt;  ScriptRuntime py = Python.CreateRuntime();&lt;br/&gt;&lt;span class="rem"&gt;//Dynamic feature only works on objects typed as 'dynamic'&lt;/span&gt;&lt;br/&gt;dynamic helloworld = py.UseFile(&lt;span class="str"&gt;&amp;quot;helloworld.py&amp;quot;&lt;/span&gt;);&lt;br/&gt;&lt;br/&gt;Console.WriteLine(&lt;span class="str"&gt;&amp;quot;helloworld.py loaded!&amp;quot;&lt;/span&gt;);&lt;br/&gt;&lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; 1000; i++)&lt;br/&gt;{&lt;br/&gt;      Console.WriteLine(helloworld.welcome(&lt;span class="str"&gt;&amp;quot;Employee #{0}&amp;quot;&lt;/span&gt;), i);&lt;br/&gt;}&lt;p&gt;这是Visual Studio 2010中使用IronPython的例子，为了运行这个程序，请下载IronPython, 例子中的的源代码如下&lt;/p&gt;def welcome(name):&lt;br/&gt;      &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;Hello '&amp;quot;&lt;/span&gt; + name + &lt;span class="str"&gt;&amp;quot;' from IronPython&amp;quot;&lt;/span&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;学到了这么多技术，最终都是为了改善产品，改善系统的可维护性。在之前的文章中我提到为应用程序添加脚本功能，可产生定制的动态的代码块，然后返回执行结果。这项功能为应用程序的灵活性提供了极大的方便。我在工作流的表达式求值，工资公式编辑器中有提到动态脚本Script.NET的能力。然而Script.NET停止开发很久了，而且我一直期盼的调试功能又没有实现出来。自己参考SharpDevelop做script debugger,没有结果，只好暂时停止对Script.NET的进一步探索与应用。现有IronPython 2.7.1 已经直接做成了Visual Studio的解决方案项目，简单方便省事。&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201201/201201050925181235.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201201/201201050925186742.png" width="784" height="420" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;几乎不用任何配置，直接安装下载回到的IronPython-2.7.1安装文件即可，它会为你的Visual Studio创建Python项目模板。在x86的电脑上，可以产生四个类型的项目模板，Console Application,WinForms Application,IronPython Silverlight Web Page，Wpf Application,而在x64的平台上，只产生了Console Application项目模板。&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;但是，这样还有点不方便，Python在这里被当成脚本语言，它的Build Action=None,意味着没有任何编译行为，这样会给代码的调试工作带来不方便之处。需要安装工具Python Tools for Visual Studio。&lt;/p&gt;&lt;p&gt;先卸载已经安装的IronPython工具包，才能继续安装Python Tools for Visual Studio。安装完成之后，项目模板又多了二项模板，Python Application和Python MPI Application。新建立一个Python Application项目&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201201/201201050925188661.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201201/201201050925198628.png" width="784" height="420" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;请先到Tools-&amp;gt;Options的Python Tools中新建一个Interpreter，在Interpreter Options中点击Add Interpreter按钮，保存退出即可。然后就可直接在编辑器中放断点，调试的体验和调试.NET语言一样，Call Stask,Intermediate Window,Watch窗口都可用，这种感觉是相当的方便。再看看Program.py的文件属性，它的Build Action=Compile。&lt;/p&gt;&lt;p&gt;在安装工具包的同时，也同时会安装Python的命令行交互程序，这个程序可以当计算器用，直接输入表达式的值，它可以马上帮助你计算出结果。再来看看下面的Python的两个例子代码，以帮助你了解和学习这种语言。&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;Lambda表达式，这个可以简化代码的编写，请看Python的实现&lt;/p&gt;func = lambda s: s * 3&lt;br/&gt;print func(&lt;span class="str"&gt;&amp;quot;peter &amp;quot;&lt;/span&gt;)  &lt;br/&gt;&lt;br/&gt;func2 = lambda a, b: a * b&lt;br/&gt;print func2(2, 3)  &lt;p&gt;调试这段代码，在Output窗口可以显示它的执行结果。Lambda表达式减少了很多不必要的代码。&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;Python的for循环语句，它的一种写法是这样的&lt;/p&gt;&lt;span class="kwrd"&gt;for&lt;/span&gt; i &lt;span class="kwrd"&gt;in&lt;/span&gt; range(0, 10,2):&lt;br/&gt;    print i&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;起始变量0，10是终止变量(不包括10)，2是步长。.NET 4中引入了并行循环，它的代码例子如下&lt;/p&gt;Parallel.For(0, Int64.MaxValue, i =&amp;gt;&lt;br/&gt;            {&lt;br/&gt;                 &lt;br/&gt;                 Console.WriteLine(&lt;span class="str"&gt;&amp;quot;i={0},thread id={1}&amp;quot;&lt;/span&gt;, i, Thread.CurrentThread.ManagedThreadId);&lt;br/&gt;                 Thread.Sleep(1000);&lt;br/&gt;            });&amp;#160;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;整理一下文章的思路，您首先要选择一门脚本语言，来为你的应用程序提供动态代码执行能力。在这里，我选择Python语言，并选择它的.NET实现版本IronPython。其次，我要对脚本与.NET host之间的代码互操作有所了解，如何把.NET的变量传到脚本中，如何传回脚本的执行结果到.NET代码中。最后，我需要一个灵活方便的脚本编辑工具，并且可以提供强大的调试功能。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/JamesLi2015/aggbug/2312678.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/JamesLi2015/archive/2012/01/05/2312678.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/JamesLi2015/archive/2011/12/31/2308353.html</id><title type="text">总结一下ERP .NET程序员必须掌握的.NET技术，掌握了这些技术工作起来才得心应手</title><summary type="text">从毕业做.NET到现在，有好几年了，自认为只能是达到熟练的水平，谈不上精通。所以，总结一下，自己到底熟练掌握了哪些.NET方面的开发技术，以此对照，看看还有哪些不足，欢迎补充。 1 .NET Framework常见的API要熟练掌握。有些API可能需要多个类型配合使用，也有必要掌握。IEntity2 clonedEntity = null;BinaryFormatter formatter = n...</summary><published>2011-12-31T01:05:00Z</published><updated>2011-12-31T01:05:00Z</updated><author><name>James Li</name><uri>http://www.cnblogs.com/JamesLi2015/</uri></author><link rel="alternate" href="http://www.cnblogs.com/JamesLi2015/archive/2011/12/31/2308353.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/JamesLi2015/archive/2011/12/31/2308353.html"/><content type="html">&lt;p&gt;从毕业做.NET到现在，有好几年了，自认为只能是达到熟练的水平，谈不上精通。所以，总结一下，自己到底熟练掌握了哪些.NET方面的开发技术，以此对照，看看还有哪些不足，欢迎补充。&lt;/p&gt; &lt;p&gt;1 .NET Framework常见的API要熟练掌握。有些API可能需要多个类型配合使用，也有必要掌握。&lt;/p&gt;IEntity2 clonedEntity = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br/&gt;BinaryFormatter formatter = &lt;span class="kwrd"&gt;new&lt;/span&gt; BinaryFormatter();&lt;br/&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; (MemoryStream memStream = &lt;span class="kwrd"&gt;new&lt;/span&gt; MemoryStream())&lt;br/&gt;{&lt;br/&gt;         formatter.Serialize(memStream, sourceEntity);&lt;br/&gt;          memStream.Seek(0, SeekOrigin.Begin);&lt;br/&gt;          clonedEntity = (IEntity2)formatter.Deserialize(memStream);&lt;br/&gt;}&lt;br&gt;&amp;nbsp;&lt;p&gt;这个例子是.NET的深拷贝(deep copy)的实现，类似于这样的例子，还有很多。这些API的组合应用是需要掌握的。经过积累后，通常都会有自己的一个Utility类型库。 &lt;br&gt;&lt;/p&gt;&lt;p&gt;2 Linq to Object。虽然Linq to SQL已经被抛弃和遗忘，但是Linq to Object还真是一项很重要的技术。如果没有这项技术，数据的查找和操作的代码会被foreach充满，这样不容易维护，而且有很多代码都是routine代码，可以省略的。&lt;/p&gt;&lt;span class="kwrd"&gt;string&lt;/span&gt;[] names = { &lt;span class="str"&gt;"Tom"&lt;/span&gt;,&lt;span class="str"&gt;"Dick"&lt;/span&gt;,&lt;span class="str"&gt;"Harry"&lt;/span&gt;,&lt;span class="str"&gt;"Mary"&lt;/span&gt;,&lt;span class="str"&gt;"Jay"&lt;/span&gt; };&lt;br/&gt;IEnumerable&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; query =&lt;br/&gt;                 from    n &lt;span class="kwrd"&gt;in&lt;/span&gt; names&lt;br/&gt;      &lt;span class="kwrd"&gt;where&lt;/span&gt;   n.Contains (&lt;span class="str"&gt;"a"&lt;/span&gt;)  &lt;span class="rem"&gt;// Filter elements&lt;/span&gt;&lt;br/&gt;      orderby n.Length          &lt;span class="rem"&gt;// Sort elements&lt;/span&gt;&lt;br/&gt;      select  n.ToUpper( );     &lt;span class="rem"&gt;// Project each element&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt; name &lt;span class="kwrd"&gt;in&lt;/span&gt; query)&lt;br/&gt;     Console.Write (name + &lt;span class="str"&gt;"/"&lt;/span&gt;);&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&lt;br/&gt;{&lt;br/&gt;font-size: small;&lt;br/&gt;color: black;&lt;br/&gt;font-family: consolas, "Courier New", courier, monospace;&lt;br/&gt;background-color: #ffffff;&lt;br/&gt;/*white-space: pre;*/&lt;br/&gt;}&lt;br/&gt;.csharpcode pre { margin: 0em; }&lt;br/&gt;.csharpcode .rem { color: #008000; }&lt;br/&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br/&gt;.csharpcode .str { color: #006080; }&lt;br/&gt;.csharpcode .op { color: #0000c0; }&lt;br/&gt;.csharpcode .preproc { color: #cc6633; }&lt;br/&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br/&gt;.csharpcode .html { color: #800000; }&lt;br/&gt;.csharpcode .attr { color: #ff0000; }&lt;br/&gt;.csharpcode .alt &lt;br/&gt;{&lt;br/&gt;background-color: #f4f4f4;&lt;br/&gt;width: 100%;&lt;br/&gt;margin: 0em;&lt;br/&gt;}&lt;br/&gt;.csharpcode .lnum { color: #606060; }&lt;br/&gt;&lt;/style&gt;&lt;p&gt;同时，与Linq搭配的技术Lambda技术，可以简化很多代码，这也需要掌握，上面的例子用Lambda技术改写一下&lt;/p&gt;&lt;span class="kwrd"&gt;string&lt;/span&gt;[] names = { &lt;span class="str"&gt;"Tom"&lt;/span&gt;,&lt;span class="str"&gt;"Dick"&lt;/span&gt;,&lt;span class="str"&gt;"Harry"&lt;/span&gt;,&lt;span class="str"&gt;"Mary"&lt;/span&gt;,&lt;span class="str"&gt;"Jay"&lt;/span&gt; };&lt;br/&gt;IEnumerable&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; query = names&lt;br/&gt;      .Where   (n =&amp;gt; n.Contains (&lt;span class="str"&gt;"a"&lt;/span&gt;))&lt;br/&gt;      .OrderBy (n =&amp;gt; n.Length)&lt;br/&gt;      .Select  (n =&amp;gt; n.ToUpper( ));&lt;br/&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt; name &lt;span class="kwrd"&gt;in&lt;/span&gt; query)&lt;br/&gt;     Console.Write (name + &lt;span class="str"&gt;"|"&lt;/span&gt;);&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;曾经有个非常流行的考试题目，考察委托的三种写法，举例如下所示&lt;/p&gt;List&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt; list = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt;();&lt;br/&gt;list.AddRange(&lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt;[] { 1, 5, 10, 20 ,33 });&lt;br/&gt; &lt;br/&gt;&lt;span class="rem"&gt;//使用传统委托语法调用FindAll&lt;/span&gt;&lt;br/&gt;Predicate&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt; callback = &lt;span class="kwrd"&gt;new&lt;/span&gt; Predicate&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt;(IsEvenNumber);&lt;br/&gt;List&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt; evenNumbers = list.FindAll(callback);&lt;br/&gt;&lt;br/&gt;&lt;span class="rem"&gt;//使用匿名方法&lt;/span&gt;&lt;br/&gt;List&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt; evenNumbers = list.FindAll(&lt;br/&gt;               &lt;span class="kwrd"&gt;delegate&lt;/span&gt;(&lt;span class="kwrd"&gt;int&lt;/span&gt; i)&lt;br/&gt;                {&lt;br/&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; (i % 2) == 0;&lt;br/&gt;                });&lt;br/&gt;&lt;br/&gt;&lt;span class="rem"&gt;//使用Lambda表达式&lt;/span&gt;&lt;br/&gt;List&amp;lt;&lt;span class="kwrd"&gt;int&lt;/span&gt;&amp;gt; evenNumbers = list.FindAll(i =&amp;gt; (i % 2) == 0);&lt;br/&gt;(代码来自于&lt;b&gt;&lt;a href="http://www.cnblogs.com/lifepoem/archive/2011/10/26/2225086.html"&gt;LINQ之路 3：C# 3.0的语言功能（下）&lt;/a&gt;&lt;/b&gt;）&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;3&amp;nbsp; .NET 4引入了新的并行编程库。这项技术不同于多线程技术，它是适应多核时代的需要。来看下面的例子程序&lt;/p&gt;&lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;double&lt;/span&gt; ParallelPi()&lt;br/&gt;{&lt;br/&gt;        &lt;span class="kwrd"&gt;double&lt;/span&gt; sum = 0.0;&lt;br/&gt;        &lt;span class="kwrd"&gt;double&lt;/span&gt; step = 1.0 / (&lt;span class="kwrd"&gt;double&lt;/span&gt;)num_steps;&lt;br/&gt;        &lt;span class="kwrd"&gt;object&lt;/span&gt; monitor = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt;();&lt;br/&gt;        Parallel.For(0, num_steps, () =&amp;gt; 0.0, (i, state, local) =&amp;gt;&lt;br/&gt;        {&lt;br/&gt;            &lt;span class="kwrd"&gt;double&lt;/span&gt; x = (i + 0.5) * step;&lt;br/&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; local + 4.0 / (1.0 + x * x);&lt;br/&gt;        }, local =&amp;gt; { &lt;span class="kwrd"&gt;lock&lt;/span&gt; (monitor) sum += local; });&lt;br/&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; step * sum;&lt;br/&gt;}&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;有了新面的Lambda表达式基础，这个例子也不难读懂。这是用并行库求PI的值。&lt;/p&gt;&lt;p&gt;.NET 4还引入了动态语言，如下的例子所示，Python的例子&lt;/p&gt;ScriptRuntime py = Python.CreateRuntime();&lt;br/&gt;&lt;span class="rem"&gt;//Dynamic feature only works on objects typed as 'dynamic'&lt;/span&gt;&lt;br/&gt;dynamic helloworld = py.UseFile(&lt;span class="str"&gt;"helloworld.py"&lt;/span&gt;);&lt;br/&gt;Console.WriteLine(&lt;span class="str"&gt;"helloworld.py loaded!"&lt;/span&gt;);&lt;br/&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; 1000; i++)&lt;br/&gt;{&lt;br/&gt;       Console.WriteLine(helloworld.welcome(&lt;span class="str"&gt;"Employee #{0}"&lt;/span&gt;), i);&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;&lt;span class="rem"&gt;//Python的代码&lt;/span&gt;&lt;br/&gt;def welcome(name):&lt;br/&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Hello '"&lt;/span&gt; + name + &lt;span class="str"&gt;"' from IronPython"&lt;/span&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;如果要改善.NET程序的性能，可以考虑使用.NET并行库。如果你在寻找脚本语言，可以寄宿到.NET中方便调用，这里的Python应该是一个很好的开始。对于.NET框架直接内置的技术，必定会有大量的第三方工具，产品来对它做Enhancement或Extension,你可以找到很称手的工具，为你的项目增加灵活性和改善性能。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;4 ORM开发技术。可以选择NHibernate，也可以选择Entity Framework。ORM技术可以让你的代码专注于业务逻辑，大大简化数据访问代码的编码与调试。此外，ORM技术支持界面与逻辑分离，强类型的数据绑定，这些好处，都可以给你的项目增加灵活性。比如保存客户的代码，用ORM技术写，是这样的&lt;/p&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; (DataAccessAdapterBase adapter =GetDataAccessAdapter())&lt;br/&gt;{&lt;br/&gt;    &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;br/&gt;    {&lt;br/&gt;        adapter.StartTransaction(IsolationLevel.ReadCommitted, &lt;span class="str"&gt;"SaveCustomer"&lt;/span&gt;);&lt;br/&gt;        adapter.SaveEntity(Customer, &lt;span class="kwrd"&gt;true&lt;/span&gt;, &lt;span class="kwrd"&gt;false&lt;/span&gt;);&lt;br/&gt;        adapter.Commit();&lt;br/&gt;    }&lt;br/&gt;    &lt;span class="kwrd"&gt;catch&lt;/span&gt;&lt;br/&gt;    {&lt;br/&gt;        adapter.Rollback();&lt;br/&gt;        &lt;span class="kwrd"&gt;throw&lt;/span&gt;;&lt;br/&gt;    }&lt;br/&gt;}&lt;p&gt;可不能小看了这几句，首先它是用代码生成器生成的，其次，对于增改数据库字段，这里不用作任何的修改，再次，界面的变动和业务逻辑的变动，也不会影响到这里。就这几项好处，可以节约大量的时间，让你专注于业务逻辑。&lt;/p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;5&amp;nbsp; 分布式的通讯技术。.NET Remoting和WCF，至少要掌握一项才行。&lt;/p&gt;&lt;p&gt;6&amp;nbsp; 界面组件包。.NET 框架自带的界面控件虽然简单好用，但不够强大。所以，推荐你选购一套流行的界面控件，为你的项目增加可读性。虽然都是说界面不重要，逻辑重要，但是我们心里也明白，界面看起来惨不忍睹，再好的逻辑和架构也也不会被客户接受。界面要做到简单，实用，说起起容易，做起来可相当不容易。这里可以选择的控件比较多，Infragistics,Syncfusion,ComponentOne，都是很著名的控件供应商。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/JamesLi2015/aggbug/2308353.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/JamesLi2015/archive/2011/12/31/2308353.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/JamesLi2015/archive/2011/12/29/2305619.html</id><title type="text">应用反射技术为Infragistics Solution设计例子程序 代码简洁而且学习的效率高</title><summary type="text">公司的ERP系统是采用Infragistics的控件，这个系列的组件非常庞大，功能很多。在学习的过程中，经常需要查找它的Sample来了解它的属性，经过一段时间的研究，就想到把它的Sample重新组织一下以方便学习。有些Sample是VB写的，只熟悉C#程序，VB可以看懂但不能用于编程开发，于是就用VB Converter转换为C#代码 点击Convert Anywan进行转换，转换正确率...</summary><published>2011-12-29T01:45:00Z</published><updated>2011-12-29T01:45:00Z</updated><author><name>James Li</name><uri>http://www.cnblogs.com/JamesLi2015/</uri></author><link rel="alternate" href="http://www.cnblogs.com/JamesLi2015/archive/2011/12/29/2305619.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/JamesLi2015/archive/2011/12/29/2305619.html"/><content type="html">&lt;p&gt;公司的ERP系统是采用Infragistics的控件，这个系列的组件非常庞大，功能很多。在学习的过程中，经常需要查找它的Sample来了解它的属性，经过一段时间的研究，就想到把它的Sample重新组织一下以方便学习。有些Sample是VB写的，只熟悉C#程序，VB可以看懂但不能用于编程开发，于是就用VB Converter转换为C#代码&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/201112290944314873.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/201112290944326335.png" width="784" height="394" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;点击Convert Anywan进行转换，转换正确率达99%，遇到索引(index)转换需要手工修改，比如C#中DataRow drow[“CustomerId”] 这样引用列，转换后是的结果是drow(“CustomerId”)。&lt;/p&gt;  &lt;p&gt;于是乎，三下五除二就把它的例子程序转移到了C#的解决方案中，形成我的Infragistics Solution。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/201112290944329956.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/201112290944321941.png" width="264" height="314" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;这样集中学习它的例子，下次忘记了查阅这个解决方案文件和记得笔记代码，效果不错。&lt;/p&gt;  &lt;p&gt;有一个地方还需要改善一下，Infragistics 公司提供的NetAdvatange Sample是一个个独立的解决方案文件。这在安装程序，维护版权方面是很有用的，但是不利于学习研究。它的每一个Sample中都有这样的代码&lt;/p&gt;  [STAThread]&lt;br/&gt;&lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main() &lt;br/&gt;{&lt;br/&gt;     Application.Run(&lt;span class="kwrd"&gt;new&lt;/span&gt; Form1());&lt;br/&gt;}&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;Form1看起来并不刺眼，通常在Sample程序中，这表示是没有任何修改的通过Visual Studio模板生成的窗体。&lt;/p&gt;&lt;p&gt;比较麻烦的是，经过我的合并与添加，最后形成这样一个文件佳结构，以UltraGrid为例子&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/201112290944333054.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/201112290944335038.png" width="284" height="378" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;Intermediate Tutorial2中还有更多的例子，如果要写代码调用它们，可能要写很多个new Form1的代码，而且要经常修改启动窗体，这样显然不合理，有些麻烦。在熟练应用了反射技术后，自然就想到了动态生成类型与调用。&lt;/p&gt;&lt;p&gt;添加一个MainForm作为启动窗体，添加treeView控件，以显示Sample中的Form，在Form_Load中增加代码&lt;/p&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; InfragisticsSolutionForm_Load(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;br/&gt;{&lt;br/&gt;     Assembly assembly = Assembly.GetExecutingAssembly();&lt;br/&gt;     TreeNode root = tree.Nodes.Add(&lt;span class="str"&gt;&amp;quot;Infragistics Solution&amp;quot;&lt;/span&gt;);&lt;br/&gt;     &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Type type &lt;span class="kwrd"&gt;in&lt;/span&gt; assembly.GetTypes())&lt;br/&gt;     {&lt;br/&gt;            TreeNode node= root.Nodes.Add(type.FullName);&lt;br/&gt;             node.Tag = type;&lt;br/&gt;      }&lt;br/&gt;      root.ExpandAll();&lt;br/&gt;}&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;这样就把这个解决方案中的Form都添加到了窗体树中，生成的窗体效果如下图所示&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/201112290944332563.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/201112290944335104.png" width="784" height="397" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;再来设计启动Sample窗体的代码，在treeView的MouseDoubleClick和Call按钮的点击事件中调用如下的代码&lt;/p&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; (tree.SelectedNode.Tag != &lt;span class="kwrd"&gt;null&lt;/span&gt; )&lt;br/&gt;{&lt;br/&gt;      Type type = tree.SelectedNode.Tag &lt;span class="kwrd"&gt;as&lt;/span&gt; Type;             &lt;br/&gt;      Form frm = Activator.CreateInstance(type) &lt;span class="kwrd"&gt;as&lt;/span&gt; Form;&lt;br/&gt;      &lt;span class="kwrd"&gt;if&lt;/span&gt; (frm != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br/&gt;      {&lt;br/&gt;           frm.Show(&lt;span class="kwrd"&gt;this&lt;/span&gt;);&lt;br/&gt;      }&lt;br/&gt;}&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;这样就轻松的完成了Sample窗体的启动。还有一个地方值得改善，每次点击Call 按钮之后，都会new窗体，这会消耗大量的内存，Form没有显示在用户界面中，并不表示它已经从内存中被GC当成垃圾回收，经过改良后的代码如下&lt;/p&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; (tree.SelectedNode.Tag != &lt;span class="kwrd"&gt;null&lt;/span&gt; )&lt;br/&gt;{&lt;br/&gt;        Type type = tree.SelectedNode.Tag &lt;span class="kwrd"&gt;as&lt;/span&gt; Type;&lt;br/&gt;        Form frm=Application.OpenForms[type.Name];&lt;br/&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (frm != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br/&gt;        {&lt;br/&gt;             &lt;span class="kwrd"&gt;if&lt;/span&gt;(!frm.Visible)&lt;br/&gt;                 frm.Show(&lt;span class="kwrd"&gt;this&lt;/span&gt;);&lt;br/&gt;             &lt;span class="kwrd"&gt;return&lt;/span&gt;;&lt;br/&gt;        }&lt;br/&gt;        frm = Activator.CreateInstance(type) &lt;span class="kwrd"&gt;as&lt;/span&gt; Form;&lt;br/&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (frm != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br/&gt;        {&lt;br/&gt;            frm.Show(&lt;span class="kwrd"&gt;this&lt;/span&gt;);&lt;br/&gt;        }&lt;br/&gt;}&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;先从Application.OpenForms查找已经开启的窗体，如果有就把它显示出来。这个代码有个问题，type.Name为Form1，如果其它的窗体也叫这个名字Form1,尽管他们在不同的命名空间中。这样，其它的Form1名称的窗体都无法打开，如果改进type.FullName,则frm每次都是null，像这样修改过之后&lt;/p&gt;Form frm=Application.OpenForms[type.FullName];&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;即使窗体已经显示出来了，frm的值也是null。查找MSDN文档，Name定义就是取自InitializeComponent&lt;/p&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; InitializeComponent()&lt;br/&gt;{&lt;br/&gt;     &lt;span class="kwrd"&gt;this&lt;/span&gt;.Name = &lt;span class="str"&gt;&amp;quot;Form1&amp;quot;&lt;/span&gt;;&lt;br/&gt;}&lt;p&gt;这种缓存的办法是失效的，无法达到节约内存的目的。 经过数次的调整与修改，最后的代码如下&lt;/p&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (tree.SelectedNode.Tag != &lt;span class="kwrd"&gt;null&lt;/span&gt; )&lt;br/&gt; {&lt;br/&gt;          Type type = tree.SelectedNode.Tag &lt;span class="kwrd"&gt;as&lt;/span&gt; Type;&lt;br/&gt;          Form frm = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br/&gt;          &lt;span class="kwrd"&gt;if&lt;/span&gt; (_types.Contains(type))&lt;br/&gt;          {               &lt;br/&gt;                &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Form t &lt;span class="kwrd"&gt;in&lt;/span&gt; _forms)&lt;br/&gt;                {&lt;br/&gt;                    &lt;span class="kwrd"&gt;if&lt;/span&gt; (t.GetType().FullName.Equals(type.FullName))&lt;br/&gt;                    {&lt;br/&gt;                          frm = t;&lt;br/&gt;                          &lt;span class="kwrd"&gt;break&lt;/span&gt;;&lt;br/&gt;                    }&lt;br/&gt;                }&lt;br/&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt;(frm.IsDisposed)&lt;br/&gt;                    frm = Activator.CreateInstance(type) &lt;span class="kwrd"&gt;as&lt;/span&gt; Form;&lt;br/&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (!frm.Visible)&lt;br/&gt;                    frm.Show(&lt;span class="kwrd"&gt;this&lt;/span&gt;);&lt;br/&gt;                  &lt;br/&gt;               &lt;span class="kwrd"&gt;return&lt;/span&gt;;&lt;br/&gt;         }&lt;br/&gt;&lt;br/&gt;         frm = Activator.CreateInstance(type) &lt;span class="kwrd"&gt;as&lt;/span&gt; Form;&lt;br/&gt;         &lt;span class="kwrd"&gt;if&lt;/span&gt; (frm != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br/&gt;         {&lt;br/&gt;             frm.Show(&lt;span class="kwrd"&gt;this&lt;/span&gt;);&lt;br/&gt;             _types.Add(type);&lt;br/&gt;             _forms.Add(frm);&lt;br/&gt;          }&lt;br/&gt;}&lt;p&gt;两个集合分别用来存放缓存的对象和实例子，定义如下&lt;/p&gt;List&amp;lt;Form&amp;gt; _forms;&lt;br/&gt;List&amp;lt;Type&amp;gt; _types;      &lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;希望能对你有帮助。&lt;/p&gt;           &lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;img src="http://www.cnblogs.com/JamesLi2015/aggbug/2305619.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/JamesLi2015/archive/2011/12/29/2305619.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/JamesLi2015/archive/2011/12/28/2304257.html</id><title type="text">Linq to LLBL Gen Pro LLBL Gen的Linq程序设计</title><summary type="text">继续讲解LLBL Gen的开发教程，这一篇学习Linq to LLBL Gen的应用。 MSDN对Linq的解释如下：LINQ（语言级集成查询）的意图就是提供一种统一且对称的方式，让程序员在广义的数据上获取和操作数据。虽然Linq to SQL已经不再更新，但是Linq to xml,Linq to Object仍然很实用，它可以简化程序代码的编写。在没有Linq的.NET 2.0时代，通常只能...</summary><published>2011-12-28T01:14:00Z</published><updated>2011-12-28T01:14:00Z</updated><author><name>James Li</name><uri>http://www.cnblogs.com/JamesLi2015/</uri></author><link rel="alternate" href="http://www.cnblogs.com/JamesLi2015/archive/2011/12/28/2304257.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/JamesLi2015/archive/2011/12/28/2304257.html"/><content type="html">&lt;p&gt;继续讲解LLBL Gen的开发教程，这一篇学习Linq to LLBL Gen的应用。&lt;/p&gt;  &lt;p&gt;MSDN对Linq的解释如下：LINQ（语言级集成查询）的意图就是提供一种统一且对称的方式，让程序员在广义的数据上获取和操作数据。虽然Linq to SQL已经不再更新，但是Linq to xml,Linq to Object仍然很实用，它可以简化程序代码的编写。在没有Linq的.NET 2.0时代，通常只能用foreach循环遍历来查找满足条件的数据。    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;LinqMetaData&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;如果要在LLBL Gen的项目中使用Linq，首先要保证你的项目属性是.NET 3.0/3.5以上，这会调用Linq的模板生成需要的元数据。在生成的DatabaseGeneric中会产生Linq的文件夹，并且增加类型LinqMetaData。它的定义如下所示&lt;/p&gt;  &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; LinqMetaData: ILinqMetaData&lt;br/&gt;{&lt;br/&gt;     &lt;span class="preproc"&gt;#region&lt;/span&gt; Class Member Declarations&lt;br/&gt;      &lt;span class="kwrd"&gt;private&lt;/span&gt; IDataAccessAdapter _adapterToUse;&lt;br/&gt;      &lt;span class="kwrd"&gt;private&lt;/span&gt; FunctionMappingStore _customFunctionMappings;&lt;br/&gt;      &lt;span class="kwrd"&gt;private&lt;/span&gt; Context _contextToUse;&lt;br/&gt;      &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br/&gt;        &lt;br/&gt;     &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;CTor. Using this ctor will leave the IDataAccessAdapter object to use empty. &lt;br /&gt;     /// To be able to execute the query, an IDataAccessAdapter instance&lt;/span&gt;&lt;br/&gt;     &lt;span class="rem"&gt;/// is required, and has to be set on the LLBLGenProProvider2 object in the query to execute. &lt;br /&gt;     ///&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br/&gt;     &lt;span class="kwrd"&gt;public&lt;/span&gt; LinqMetaData() : &lt;span class="kwrd"&gt;this&lt;/span&gt;(&lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br/&gt;     {&lt;br/&gt;     }&lt;br/&gt;}&lt;p&gt;这里省略了一些方法和属性，请参考生成的类型来学习它的代码。要使用Linq,请传入当前项目的DataAccessAdapter&lt;/p&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt;(DataAccessAdapter adapter = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataAccessAdapter())&lt;br/&gt;{&lt;br/&gt;    LinqMetaData metaData = &lt;span class="kwrd"&gt;new&lt;/span&gt; LinqMetaData(adapter);&lt;br/&gt;    var q = from c &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer&lt;br/&gt;            &lt;span class="kwrd"&gt;where&lt;/span&gt; c.Country==&lt;span class="str"&gt;&amp;quot;USA&amp;quot;&lt;/span&gt;&lt;br/&gt;            select c;&lt;br/&gt;    &lt;span class="rem"&gt;// enumerate over q here so it gets executed&lt;/span&gt;&lt;br/&gt;}&lt;p&gt;为什么可以这样的写？因为LinqMetaData提供了Customers的集合属性，定义如下所示&lt;/p&gt;&lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;returns the datasource to use in a Linq query when targeting CustomerEntity instances in the database.&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; DataSource2&amp;lt;CustomerEntity&amp;gt; Customer&lt;br/&gt;{&lt;br/&gt;   get { &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; DataSource2&amp;lt;CustomerEntity&amp;gt;(_adapterToUse, &lt;span class="kwrd"&gt;new&lt;/span&gt; ElementCreator(),                     _customFunctionMappings, _contextToUse); }&lt;br/&gt;}&lt;p&gt;LLBL Gen提供了两种模式的代码调用方式：Adapter和SelfServicing，导致同一种类型要定义二次。比如SelfServicing中实体定义为IEntity，而Adapter则定义于IEntity2，在名称后面加一个数字2。以此类推，凡是类型名后面有数字2的，表示它适用于Adapter模式。Customer属性是定义一个数据源对象。&lt;/p&gt;&lt;p&gt;在这里，推荐安装测试工具软件TestDriven.NET,它的Personal版本完全免费。在任何一个.NET项目文件中，新建立一个方法，点击右键Test With-&amp;gt;Debugger，很方便的调试一段代码。因为这个软件，我就再也没有使用很著名的代码片段编辑工具Snippet Compiler，TestDriven.NET会让带给你编写.NET测试代码非常便利的体验。   &lt;br /&gt;  &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;转化Linq 查询结果&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;使用Linq to LLBL Gen查询数据之后，如果要把数据绑定到界面中，则需要提供成Entity2或EntityCollection样式。&lt;/p&gt;&lt;p&gt;这里有ILLBLGenProQuery接口用于转化Linq查询结果，以减少我们自已转化的代码。&lt;/p&gt;var q = from c &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer &lt;br /&gt;        &lt;span class="kwrd"&gt;where&lt;/span&gt; c.Country==&lt;span class="str"&gt;&amp;quot;Germany&amp;quot;&lt;/span&gt;  &lt;br /&gt;        select c;&lt;br/&gt;EntityCollection&amp;lt;CustomerEntity&amp;gt; customers = &lt;br/&gt;    ((ILLBLGenProQuery)q).Execute&amp;lt;EntityCollection&amp;lt;CustomerEntity&amp;gt;&amp;gt;();&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;如代码所示，customers就可以直接用于绑定到界面的GridView或DataGridView中。&lt;/p&gt;&lt;p&gt;写到这里，发现Windows Live Writer的Insert Code有一个小bug：对Linq查询中的from/select关键字没有高亮显示。瑕不掩玉，这个Insert Code工具帮助我的博客中的规范化的代码方面产生了重要作用。   &lt;br /&gt;  &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Group by 分组&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;按照国家和城市为组，对客户进行分类&lt;/p&gt;var q = from c &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer&lt;br/&gt;        group c by &lt;span class="kwrd"&gt;new&lt;/span&gt; { c.Country, c.City } into g&lt;br/&gt;        select &lt;span class="kwrd"&gt;new&lt;/span&gt; { g.Key, g.Count()};&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;按照客户的国家分类&lt;/p&gt;var q = from c &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer&lt;br/&gt;        group c by c.Country into g&lt;br/&gt;        select g;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&amp;#160;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&lt;strong&gt;Order By 排序&lt;/strong&gt;&lt;/p&gt;var q = from c &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer&lt;br/&gt;        orderby c.CustomerId[1]&lt;br/&gt;        select c;&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;CustomerEntity的CustomerId属性是一个字符串，按照它的第二个字母排序。   &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;  &lt;br /&gt;Queryable: Contains 包含的查询&lt;/strong&gt;&lt;/p&gt;&lt;span class="rem"&gt;// Query 1, 检查实体是否在集合中 simple entity check in entity list&lt;/span&gt;&lt;br/&gt;var q = from c &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer&lt;br/&gt;        &lt;span class="kwrd"&gt;where&lt;/span&gt; c.Orders.Where(o=&amp;gt;o.EmployeeId==3).Contains(order)&lt;br/&gt;        select c;&lt;br/&gt;&lt;br/&gt;&lt;span class="rem"&gt;// Query 2, 操作数是查询结果的实体集 operand is entity which is result of query&lt;/span&gt;&lt;br/&gt;var q = from c &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer&lt;br/&gt;        &lt;span class="kwrd"&gt;where&lt;/span&gt; c.Orders.Contains(&lt;br/&gt;                 (from o &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Order &lt;br/&gt;                  &lt;span class="kwrd"&gt;where&lt;/span&gt; o.EmployeeId == 2 select o).First())&lt;br/&gt;        select c;&lt;br/&gt;&lt;br/&gt;&lt;span class="rem"&gt;// Query 3, 操作数和源都是查询operand and source are both queries.&lt;/span&gt;&lt;br/&gt;var q = from c &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer&lt;br/&gt;        &lt;span class="kwrd"&gt;where&lt;/span&gt; c.Orders.Where(o =&amp;gt; o.EmployeeId == 2).Contains(&lt;br/&gt;                   (from o &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Order &lt;br/&gt;                    &lt;span class="kwrd"&gt;where&lt;/span&gt; o.EmployeeId == 2 select o).First())&lt;br/&gt;        select c;&lt;br/&gt;&lt;br/&gt;&lt;span class="rem"&gt;// Query 4, 查询中的常量比较 constant compare with value from query. Yes this is different.&lt;/span&gt;&lt;br/&gt;var q = from c &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer&lt;br/&gt;        &lt;span class="kwrd"&gt;where&lt;/span&gt; c.Orders.Where(o =&amp;gt; o.EmployeeId &amp;gt; 3).Select(o =&amp;gt; o.ShipVia).Contains(2)&lt;br/&gt;        select c;&lt;br/&gt;&lt;br/&gt;&lt;span class="rem"&gt;// Query 5, 检查常量表是否在查询结果中 check if a constant tuple is in the result of a query&lt;/span&gt;&lt;br/&gt;var q = from c &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer&lt;br/&gt;        &lt;span class="kwrd"&gt;where&lt;/span&gt; c.Orders.Select(oc =&amp;gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; { EID = oc.EmployeeId, CID = oc.CustomerId }).Contains(&lt;br/&gt;                         &lt;span class="kwrd"&gt;new&lt;/span&gt; { EID = (&lt;span class="kwrd"&gt;int&lt;/span&gt;?)1, CID = &lt;span class="str"&gt;&amp;quot;CHOPS&amp;quot;&lt;/span&gt; })&lt;br/&gt;        select c;&lt;br/&gt;&lt;br/&gt;&lt;span class="rem"&gt;// Query 6, as 5 but now compare with a tuple created with a query&lt;/span&gt;&lt;br/&gt;var q = from c &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer&lt;br/&gt;        &lt;span class="kwrd"&gt;where&lt;/span&gt; c.Orders.Select(oc =&amp;gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; { EID = oc.EmployeeId, CID = oc.CustomerId }).Contains(&lt;br/&gt;                      (from o &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Order &lt;span class="kwrd"&gt;where&lt;/span&gt; o.CustomerId == &lt;span class="str"&gt;&amp;quot;CHOPS&amp;quot;&lt;/span&gt; &lt;br/&gt;                       select &lt;span class="kwrd"&gt;new&lt;/span&gt; { EID = o.EmployeeId, CID = o.CustomerId }).First())&lt;br/&gt;        select c;&lt;br/&gt;&lt;br/&gt;&lt;span class="rem"&gt;// Query 7, 检查实体的属性是否包含指定的常量集合&lt;/span&gt;&lt;span class="rem"&gt;   checking if the value of a field in an entity is in a list of constants&lt;/span&gt;&lt;br/&gt;List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; countries = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;() { &lt;span class="str"&gt;&amp;quot;USA&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;UK&amp;quot;&lt;/span&gt; };&lt;br/&gt;var q = from c &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer&lt;br/&gt;        &lt;span class="kwrd"&gt;where&lt;/span&gt; countries.Contains(c.Country)&lt;br/&gt;        select c;&lt;br/&gt;&lt;br/&gt;&lt;span class="rem"&gt;// Query 8, 与7对比，换成IEnumerable。as 7 but now with an IEnumerable&lt;/span&gt;&lt;br/&gt;LinkedList&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; countries = &lt;span class="kwrd"&gt;new&lt;/span&gt; LinkedList&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(&lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;[] { &lt;span class="str"&gt;&amp;quot;USA&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;UK&amp;quot;&lt;/span&gt;});&lt;br/&gt;var q = from c &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer&lt;br/&gt;        &lt;span class="kwrd"&gt;where&lt;/span&gt; countries.Contains(c.Country)&lt;br/&gt;        select c;&lt;br/&gt;&lt;br/&gt;&lt;span class="rem"&gt;// Query 9, combination of 2 queries where the first is merged with the second and&lt;/span&gt;&lt;br/&gt;&lt;span class="rem"&gt;// only the second is executed. (this is one of the reasons why you have to write &lt;/span&gt;&lt;br/&gt;&lt;span class="rem"&gt;// your own Funcletizer code.&lt;/span&gt;&lt;br/&gt;var q1 = (from c &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer&lt;br/&gt;          select c.Country).Distinct();&lt;br/&gt;var q2 = from c &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer&lt;br/&gt;         &lt;span class="kwrd"&gt;where&lt;/span&gt; q1.Contains(c.Country)&lt;br/&gt;         select c;&lt;br/&gt;&lt;br/&gt;&lt;span class="rem"&gt;// Query 10, as 7 but now with an array obtained from another array.&lt;/span&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;string&lt;/span&gt;[][] countries = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;[1][] { &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;[] { &lt;span class="str"&gt;&amp;quot;USA&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;UK&amp;quot;&lt;/span&gt; } };&lt;br/&gt;var q = from c &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer&lt;br/&gt;        &lt;span class="kwrd"&gt;where&lt;/span&gt; countries[0].Contains(c.Country)&lt;br/&gt;        select c;&lt;br/&gt;&lt;br/&gt;&lt;span class="rem"&gt;// Query 11, complex contains query with comparison of in-memory object list&lt;/span&gt;&lt;br/&gt;List&amp;lt;Pair&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;&amp;gt; countryCities = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;Pair&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;&amp;gt;();&lt;br/&gt;countryCities.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; Pair&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(&lt;span class="str"&gt;&amp;quot;USA&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;Portland&amp;quot;&lt;/span&gt;));&lt;br/&gt;countryCities.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; Pair&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(&lt;span class="str"&gt;&amp;quot;Brazil&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;Sao Paulo&amp;quot;&lt;/span&gt;));&lt;br/&gt;&lt;br/&gt;&lt;span class="rem"&gt;// now fetch all customers which have a tuple of country/city in the list of countryCities.&lt;/span&gt;&lt;br/&gt;var q = from c &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer&lt;br/&gt;        &lt;span class="kwrd"&gt;where&lt;/span&gt; countryCities.Contains(&lt;br/&gt;                   (from c2 &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer&lt;br/&gt;                    &lt;span class="kwrd"&gt;where&lt;/span&gt; c2.CustomerId == c.CustomerId&lt;br/&gt;                    select &lt;span class="kwrd"&gt;new&lt;/span&gt; Pair&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;() &lt;br/&gt;                         { Value1 = c2.Country, Value2 = c2.City }).First())&lt;br/&gt;        select c;&lt;p&gt;Linq的查询有些复杂，如果不能理解，可以在工作中需要用到的时候再来仔细体会。&lt;/p&gt;&amp;#160;&lt;p&gt;&lt;strong&gt;Excluding / Including fields&amp;#160; 不包含/包含字段&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这个需求很重要。在写SQL语句时，不要写SELECT *，而是用具体的字段名，Excluding / Including 也就是用来指定需要SELECT出来的字段名。下面的查询，在查询结果集中不包括Photo和Notes字段。&lt;/p&gt;var q = (from e &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Employee&lt;br/&gt;         select e).ExcludeFields(e=&amp;gt;e.Photo, e=&amp;gt;e.Notes);&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&amp;#160;&lt;p&gt;&lt;strong&gt;Calling an in-memory method in the projection 在Linq投影中调用方法&lt;/strong&gt;&lt;/p&gt;&lt;span class="rem"&gt;/// Utility class which obtains value from a webservice&lt;/span&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; InMemoryCallExample&lt;br/&gt;{&lt;br/&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; GetInterestRate(&lt;span class="kwrd"&gt;string&lt;/span&gt; customerId)&lt;br/&gt;    {&lt;br/&gt;         &lt;span class="kwrd"&gt;return&lt;/span&gt; MyService.GetInterestRate(customerId);&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;&lt;span class="rem"&gt;// this class can now be used in the following query:&lt;/span&gt;&lt;br/&gt;var q = from o &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Order&lt;br/&gt;        select &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;br/&gt;        {&lt;br/&gt;            o.OrderId,&lt;br/&gt;            InterestRate = InMemoryCallExample.GetInterestRate(o.CustomerId)&lt;br/&gt;        };&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;在Linq的返回结果中调用方法，select new产生一个匿名对象，可以对它进行再调用方法处理加工。&lt;/p&gt;&lt;p&gt;也可以直接用Lambda表达式来完成这样的操作，例子代码如下所示&lt;/p&gt;Func&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; stringChopper = s=&amp;gt;s.Substring(0, 3);&lt;br/&gt;&lt;br/&gt;&lt;span class="rem"&gt;// this function can now be used in a query:&lt;/span&gt;&lt;br/&gt;var q = from c &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer&lt;br/&gt;        select stringChopper(c.CompanyName); &lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Prefetch paths 子查询&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;方法 1: WithPath and PathEdges&lt;/p&gt;&lt;span class="rem"&gt;// query  A&lt;/span&gt;&lt;br/&gt;var q =  from c &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer.WithPath(...) select c;&lt;br/&gt;&lt;br/&gt;&lt;span class="rem"&gt;// query  B&lt;/span&gt;&lt;br/&gt;var q =  (from c &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer select c).WithPath(...);&lt;br/&gt;&lt;br/&gt;&lt;span class="rem"&gt;// query  C&lt;/span&gt;&lt;br/&gt;var q =  (from c &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer.WithPath(...) &lt;span class="kwrd"&gt;where&lt;/span&gt; ... select c) join o &lt;span class="kwrd"&gt;in&lt;/span&gt;  metaData.Order on ...&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;方法2：WithPath and Lambda expressions&lt;/p&gt;var q = (from c &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Customer&lt;br/&gt;         &lt;span class="kwrd"&gt;where&lt;/span&gt; c.Country==&lt;span class="str"&gt;&amp;quot;UK&amp;quot;&lt;/span&gt;&lt;br/&gt;         select c).WithPath(p=&amp;gt;p.Prefetch(c=&amp;gt;c.Orders));&lt;br /&gt;&amp;#160;&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Function mappings 函数映射&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;从开头的一段代码中我们看到，Linq to LLBL Gen会产生直接的数据库查询动作。查询数据库时，ORM框架也会调用一些数据库系统的函数，比如SUM,AVG或是自定义的函数，这就要求有一种机制来定义函数的调用方法。&lt;/p&gt;&lt;p&gt;数据库函数定义代码如下&lt;/p&gt;&lt;span class="kwrd"&gt;ALTER&lt;/span&gt;   &lt;span class="kwrd"&gt;FUNCTION&lt;/span&gt; fn_CalculateOrderTotal(@orderID &lt;span class="kwrd"&gt;int&lt;/span&gt;, @useDiscounts &lt;span class="kwrd"&gt;bit&lt;/span&gt;)&lt;br/&gt;&lt;span class="kwrd"&gt;RETURNS&lt;/span&gt; &lt;span class="kwrd"&gt;DECIMAL&lt;/span&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;AS&lt;/span&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @toReturn &lt;span class="kwrd"&gt;DECIMAL&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; @toReturn = &lt;span class="kwrd"&gt;SUM&lt;/span&gt;((UnitPrice-(Discount * @useDiscounts)) * Quantity)&lt;br/&gt;    &lt;span class="kwrd"&gt;FROM&lt;/span&gt; [&lt;span class="kwrd"&gt;Order&lt;/span&gt; Details] &lt;br/&gt;    &lt;span class="kwrd"&gt;WHERE&lt;/span&gt; OrderID = @orderID&lt;br/&gt;    &lt;span class="kwrd"&gt;GROUP&lt;/span&gt; &lt;span class="kwrd"&gt;BY&lt;/span&gt; OrderID&lt;br/&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;RETURN&lt;/span&gt; @toReturn&lt;br/&gt;END&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;LLBL Gen的代码生成工具会对这个函数进行.NET封装调用，产生如下所示的代码以调用数据库中的fn_CalculateOrderTotal&lt;/p&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; NorthwindFunctions&lt;br/&gt;{&lt;br/&gt;     &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;decimal&lt;/span&gt; CalculateOrderTotal(&lt;span class="kwrd"&gt;int&lt;/span&gt; orderId, &lt;span class="kwrd"&gt;bool&lt;/span&gt; useDiscounts)&lt;br/&gt;    {&lt;br/&gt;        &lt;span class="rem"&gt;// empty body, as it's just here to make the query compile. The call is converted to a SQL function.&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; 0.0M;&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; NorthwindFunctionMappings : FunctionMappingStore&lt;br/&gt;{&lt;br/&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; NorthwindFunctionMappings() : &lt;span class="kwrd"&gt;base&lt;/span&gt;()&lt;br/&gt;    {&lt;br/&gt;        &lt;span class="kwrd"&gt;this&lt;/span&gt;.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; FunctionMapping(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(NorthwindFunctions), &lt;span class="str"&gt;&amp;quot;CalculateOrderTotal&amp;quot;&lt;/span&gt;, 2, &lt;br/&gt;                        &lt;span class="str"&gt;&amp;quot;fn_CalculateOrderTotal({0}, {1})&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;Northwind&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;dbo&amp;quot;&lt;/span&gt;));&lt;br/&gt;    }&lt;br/&gt;}&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;NorthwindFunctions类型会根据数据库中的函数，生成.NET调用代码。NorthwindFunctionMappings 则把这个函数转化为Linq to LLBL Gen的映射定义方式，最后看到应用代码是这样的&lt;/p&gt;metaData.CustomFunctionMappings = &lt;span class="kwrd"&gt;new&lt;/span&gt; NorthwindFunctionMappings();&lt;br/&gt;var q = from o &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Order&lt;br/&gt;             &lt;span class="kwrd"&gt;where&lt;/span&gt; o.CustomerId == &lt;span class="str"&gt;&amp;quot;CHOPS&amp;quot;&lt;/span&gt;&lt;br/&gt;             select &lt;span class="kwrd"&gt;new&lt;/span&gt; { o.OrderId, OrderTotal = NorthwindFunctions.CalculateOrderTotal(o.OrderId, &lt;span class="kwrd"&gt;true&lt;/span&gt;) };&lt;br /&gt;&amp;#160;&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Full-text search 全文索引 &lt;/strong&gt;&lt;/p&gt;&lt;p&gt;以上面为基础，实现Linq中的全文索引就比较容易，对于SQL Server，在自定义的数据库函数中调有数据Contains。&lt;/p&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; NorthwindFunctions&lt;br/&gt;{&lt;br/&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; FullTextSearch(&lt;span class="kwrd"&gt;string&lt;/span&gt; fieldToSearch, &lt;span class="kwrd"&gt;string&lt;/span&gt; toFind)&lt;br/&gt;    {&lt;br/&gt;        &lt;span class="rem"&gt;// empty body, as it's just here to make the query compile. The call is converted to a SQL function.&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;&lt;span class="rem"&gt;/// Class which defines the custom mapping between NorthwindFunctions.FullTextSearch and CONTAINS()&lt;/span&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; NorthwindFunctionMappings : FunctionMappingStore&lt;br/&gt;{&lt;br/&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; NorthwindFunctionMappings() : &lt;span class="kwrd"&gt;base&lt;/span&gt;()&lt;br/&gt;    {&lt;br/&gt;         &lt;span class="rem"&gt;// FullTextSearch(2) on 1 field&lt;/span&gt;&lt;br/&gt;         &lt;span class="kwrd"&gt;this&lt;/span&gt;.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; FunctionMapping(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(NorthwindFunctions), &lt;span class="str"&gt;&amp;quot;FullTextSearch&amp;quot;&lt;/span&gt;, 2, &lt;span class="str"&gt;&amp;quot;CONTAINS({0}, {1})&amp;quot;&lt;/span&gt;));&lt;br/&gt;    }&lt;br/&gt;}&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;应用代码与前面的相同，在使用前设置CustomFunctionMappings&lt;/p&gt;metaData.CustomFunctionMappings = &lt;span class="kwrd"&gt;new&lt;/span&gt; NorthwindFunctionMappings();&lt;br/&gt;&lt;span class="rem"&gt;// fetch the employees which have 'BA' in their Notes field which is Full text search enabled.&lt;/span&gt;&lt;br/&gt;var q = from e &lt;span class="kwrd"&gt;in&lt;/span&gt; metaData.Employee&lt;br/&gt;        &lt;span class="kwrd"&gt;where&lt;/span&gt; NorthwindFunctions.FullTextSearch(e.Notes, &lt;span class="str"&gt;&amp;quot;BA&amp;quot;&lt;/span&gt;)&lt;br/&gt;        select e;&lt;p&gt;经过这两个例子，就引伸出关于调用数据库中函数的方法，也就是如何调用我们经常用到的SQL函数SUM/AVG。请参考帮助文档中的Supported default method / property mappings to functions。&lt;/p&gt;&lt;p&gt;一般来说，调用数据库的函数比前面的调用自定义函数更简单，ORM框架会预先设置好这些函数的映射。对于SQL Server 2005及以上的版本，因为引入了CLR Host技术，会略有些不同。如果我们的SQL代码不涉及CLR 函数和类型，调用方法和前面的一样。如果有涉及，要确保添加正确的的Function Mapping。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/JamesLi2015/aggbug/2304257.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/JamesLi2015/archive/2011/12/28/2304257.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/JamesLi2015/archive/2011/12/27/2303020.html</id><title type="text">LLBL Gen 元数据编程 LLBL Gen Meta-data Programming</title><summary type="text">LLBL Gen作为ORM工具，有时候为了能生成一些基础的元数据，也需要了解它的对象及其之前的关系，这在通用的框架代码中的作用更加明显。举例说明，它生成的解决方案视图一般是这样的 现在有如下的需求需要满足，以提供基础的元数据，参考测试代码如下 string AssemblyFile = @"E:\Solution\Enterprise\Bin\Northwind.CRM.Business...</summary><published>2011-12-27T01:30:00Z</published><updated>2011-12-27T01:30:00Z</updated><author><name>James Li</name><uri>http://www.cnblogs.com/JamesLi2015/</uri></author><link rel="alternate" href="http://www.cnblogs.com/JamesLi2015/archive/2011/12/27/2303020.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/JamesLi2015/archive/2011/12/27/2303020.html"/><content type="html">&lt;p&gt;LLBL Gen作为ORM工具，有时候为了能生成一些基础的元数据，也需要了解它的对象及其之前的关系，这在通用的框架代码中的作用更加明显。举例说明，它生成的解决方案视图一般是这样的&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/201112270930192067.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/201112270930191021.png" width="224" height="294" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;现在有如下的需求需要满足，以提供基础的元数据，参考测试代码如下&lt;/p&gt;  &lt;span class="kwrd"&gt;string&lt;/span&gt; AssemblyFile = &lt;span class="str"&gt;@&amp;quot;E:\Solution\Enterprise\Bin\Northwind.CRM.BusinessLogic.dll&amp;quot;&lt;/span&gt;;&lt;br/&gt;&lt;span class="kwrd"&gt;string&lt;/span&gt; TableName = &lt;span class="str"&gt;&amp;quot;Employees&amp;quot;&lt;/span&gt;;&lt;br/&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;string&lt;/span&gt; projectName = EntityClassHelper.PrefixProjectName(AssemblyFile);&lt;br/&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;string&lt;/span&gt; entity = EntityClassHelper.GetEntityName(TableName, AssemblyFile);&lt;br/&gt;&lt;span class="kwrd"&gt;string&lt;/span&gt; entityName = &lt;span class="str"&gt;&amp;quot;EmployeeEntity&amp;quot;&lt;/span&gt;;&lt;br/&gt;&lt;span class="kwrd"&gt;string&lt;/span&gt; str = EntityClassHelper.TrimEntityName(entityName);&lt;br/&gt;&lt;br/&gt;IEntity2 currencyEntity = EntityClassHelper.GetEntityObject(TableName, AssemblyFile);&lt;br/&gt;&lt;span class="kwrd"&gt;string&lt;/span&gt; typeName = &lt;span class="str"&gt;&amp;quot;EmployeeEntity&amp;quot;&lt;/span&gt;;&lt;br/&gt;&lt;span class="kwrd"&gt;string&lt;/span&gt; table = EntityClassHelper.GetSourceTableName(typeName, AssemblyFile);&lt;br/&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;string&lt;/span&gt; entityColumnName = EntityClassHelper.GetObjectProperyName(AssemblyFile, TableName, &lt;span class="str"&gt;&amp;quot;EmployeeId&amp;quot;&lt;/span&gt;);&lt;br/&gt;entityColumnName = EntityClassHelper.GetObjectProperyName(AssemblyFile, TableName, &lt;span class="str"&gt;&amp;quot;LastName&amp;quot;&lt;/span&gt;);&lt;br/&gt;List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; path = EntityClassHelper.GetPrefetchPath(AssemblyFile, TableName);&lt;br/&gt;&lt;br/&gt;IEntity2 entity2 = EntityClassHelper.GetEntityObject(TableName, AssemblyFile);&lt;br/&gt;List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; relations = EntityClassHelper.GetPrefetchPathEx(entity2);&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;需求列出如下图表所示&lt;/p&gt;&lt;table border="1" cellspacing="0" cellpadding="2" width="768"&gt;&lt;tbody&gt;    &lt;tr&gt;      &lt;td valign="top" width="81" align="center"&gt;序号&lt;/td&gt;      &lt;td valign="top" width="685" align="center"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 需求描述&lt;/td&gt;    &lt;/tr&gt;    &lt;tr&gt;      &lt;td valign="top" width="82" align="center"&gt;1&lt;/td&gt;      &lt;td valign="top" width="684"&gt;如何获取LLBL Gen代码生成器生成的项目名称，这可以确定类型所在的命名空间&lt;/td&gt;    &lt;/tr&gt;    &lt;tr&gt;      &lt;td valign="top" width="83" align="center"&gt;2&lt;/td&gt;      &lt;td valign="top" width="683"&gt;如何根据数据库表名(Customers)，获取它对应的生成的实体名(CustomerEntity)&lt;/td&gt;    &lt;/tr&gt;    &lt;tr&gt;      &lt;td valign="top" width="84" align="center"&gt;3&lt;/td&gt;      &lt;td valign="top" width="682"&gt;如何根据实体名(CustomerEntity)，获取它映射到的数据库表名(Customers)&lt;/td&gt;    &lt;/tr&gt;    &lt;tr&gt;      &lt;td valign="top" width="84" align="center"&gt;4&lt;/td&gt;      &lt;td valign="top" width="682"&gt;如何根据实体名，获取它的主键属性/字段&lt;/td&gt;    &lt;/tr&gt;    &lt;tr&gt;      &lt;td valign="top" width="84" align="center"&gt;5&lt;/td&gt;      &lt;td valign="top" width="682"&gt;如何根据表名及指定的字段表，获取对应的生成的实体的属性&lt;/td&gt;    &lt;/tr&gt;    &lt;tr&gt;      &lt;td valign="top" width="84" align="center"&gt;6&lt;/td&gt;      &lt;td valign="top" width="682"&gt;如何获取实体的子集合的关系&lt;/td&gt;    &lt;/tr&gt;  &lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;项目名称空间&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/201112270930209102.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/201112270930209135.png" width="684" height="330" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;这里要获取的就是Root namespace，顶层的命名空间，依照这个名称，从而可以得到实体所在的名称空间。&lt;/p&gt;&lt;p&gt;LLBL Gen从3.x开始，项目文件改用xml配置文件，这为大量的第三方工具的产生提供的便利。如果要获取上图所示的Root namespace，可以采用Xml技术(XmlDocument)或Linq to Xml读取它的配置节&lt;/p&gt; &amp;lt;CodeGenerationCyclePreferences&amp;gt;&lt;br/&gt;    &amp;lt;OutputType Value=&lt;span class="str"&gt;&amp;quot;3&amp;quot;&lt;/span&gt;&amp;gt;&lt;br/&gt;      &amp;lt;LastUsedPreferences&amp;gt;&lt;br/&gt;        &amp;lt;DestinationRootFolder Value=&lt;span class="str"&gt;&amp;quot;E:\Solution\Development\MIS Solution\Source\Enterprise\BusinessLogic&amp;quot;&lt;/span&gt; /&amp;gt;&lt;br/&gt;        &amp;lt;FrameworkName Value=&lt;span class="str"&gt;&amp;quot;LLBLGen Pro Runtime Framework&amp;quot;&lt;/span&gt; /&amp;gt;&lt;br/&gt;        &amp;lt;LanguageName Value=&lt;span class="str"&gt;&amp;quot;C#&amp;quot;&lt;/span&gt; /&amp;gt;&lt;br/&gt;        &amp;lt;PlatformName Value=&lt;span class="str"&gt;&amp;quot;.NET 3.5&amp;quot;&lt;/span&gt; /&amp;gt;&lt;br/&gt;        &amp;lt;PresetName Value=&lt;span class="str"&gt;&amp;quot;Northwind&amp;quot;&lt;/span&gt; /&amp;gt;&lt;br/&gt;        &amp;lt;RootNamespace Value=&lt;span class="str"&gt;&amp;quot;Foundation.Northwind&amp;quot;&lt;/span&gt; /&amp;gt;&lt;br/&gt;        &amp;lt;TemplateGroup Value=&lt;span class="str"&gt;&amp;quot;Adapter&amp;quot;&lt;/span&gt; /&amp;gt;&lt;br/&gt;        &amp;lt;TemplateBindings&amp;gt;&lt;br/&gt;          &amp;lt;Binding Name=&lt;span class="str"&gt;&amp;quot;ISL Template&amp;quot;&lt;/span&gt; /&amp;gt;&lt;br/&gt;          &amp;lt;Binding Name=&lt;span class="str"&gt;&amp;quot;SD.AdditionalTemplates.DbEditor.Net2.0 v3.x&amp;quot;&lt;/span&gt; /&amp;gt;&lt;br/&gt;          &amp;lt;Binding Name=&lt;span class="str"&gt;&amp;quot;SD.TemplateBindings.SharedTemplates.NET35&amp;quot;&lt;/span&gt; /&amp;gt;&lt;br/&gt;          &amp;lt;Binding Name=&lt;span class="str"&gt;&amp;quot;SD.TemplateBindings.SqlServerSpecific.NET20&amp;quot;&lt;/span&gt; /&amp;gt;&lt;br/&gt;          &amp;lt;Binding Name=&lt;span class="str"&gt;&amp;quot;SD.TemplateBindings.SharedTemplates.NET20&amp;quot;&lt;/span&gt; /&amp;gt;&lt;br/&gt;          &amp;lt;Binding Name=&lt;span class="str"&gt;&amp;quot;SD.TemplateBindings.General&amp;quot;&lt;/span&gt; /&amp;gt;&lt;br/&gt;        &amp;lt;/TemplateBindings&amp;gt;&lt;br/&gt;      &amp;lt;/LastUsedPreferences&amp;gt;&lt;br/&gt;    &amp;lt;/OutputType&amp;gt;&lt;br/&gt;  &amp;lt;/CodeGenerationCyclePreferences&amp;gt;&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;如上面的Xml文本所示，RootNamespace就是我们需要的顶层命名空间。&lt;/p&gt;&lt;p&gt;观察LLBL Gen生成的项目文件，它的实体定义的代码所下的例子所示&lt;/p&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; SD.LLBLGen.Pro.ORMSupportClasses;&lt;br/&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; Northwind.DAL.EntityClasses&lt;br/&gt;{&lt;br/&gt;    &lt;span class="rem"&gt;// __LLBLGENPRO_USER_CODE_REGION_START AdditionalNamespaces&lt;/span&gt;&lt;br/&gt;    &lt;span class="rem"&gt;// __LLBLGENPRO_USER_CODE_REGION_END&lt;/span&gt;&lt;br/&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;Entity class which represents the entity 'Category'.&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br/&gt;    [Serializable]&lt;br/&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;partial&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CategoryEntity : CommonEntityBase&lt;br/&gt;        &lt;span class="rem"&gt;// __LLBLGENPRO_USER_CODE_REGION_START AdditionalInterfaces&lt;/span&gt;&lt;br/&gt;        &lt;span class="rem"&gt;// __LLBLGENPRO_USER_CODE_REGION_END    &lt;/span&gt;&lt;br/&gt;    {&lt;br/&gt;    }&lt;br/&gt;}&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;反射生成的解决方案文件类库，获取它的类型，如果是IEntity2(Adapter模式),去掉必须的EntityClasses，前面的部分即是我们需要的顶层(Root namespace)命名空间，实现代码如下所示&lt;/p&gt;Assembly assebly=Assembly.Load(businessLogic); &lt;br/&gt;Type[] types = assembly.GetTypes();&lt;br/&gt;&lt;span class="kwrd"&gt;string&lt;/span&gt; rootNamespace = &lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;;            &lt;br/&gt;&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Type type &lt;span class="kwrd"&gt;in&lt;/span&gt; types)&lt;br/&gt;{&lt;br/&gt;       &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(type.Namespace))&lt;br/&gt;       {&lt;br/&gt;                    &lt;span class="kwrd"&gt;string&lt;/span&gt; nspace = type.Namespace.Substring(type.Namespace.LastIndexOf(&lt;span class="str"&gt;'.'&lt;/span&gt;) + 1);&lt;br/&gt;                    &lt;span class="kwrd"&gt;if&lt;/span&gt; (type.Name.EndsWith(&lt;span class="str"&gt;&amp;quot;Entity&amp;quot;&lt;/span&gt;) &amp;amp; nspace == &lt;span class="str"&gt;&amp;quot;EntityClasses&amp;quot;&lt;/span&gt;)&lt;br/&gt;                    {&lt;br/&gt;                        rootNamespace = type.Namespace;&lt;br/&gt;                        &lt;span class="kwrd"&gt;int&lt;/span&gt; idx = rootNamespace .LastIndexOf(&lt;span class="str"&gt;&amp;quot;.&amp;quot;&lt;/span&gt;);&lt;br/&gt;                        rootNamespace  = rootNamespace .Substring(0, idx);&lt;br/&gt;                        &lt;span class="kwrd"&gt;break&lt;/span&gt;;&lt;br/&gt;                    }&lt;br/&gt;       }                 }&lt;p&gt;变量rootNamespace就是我需要的顶层命名空间。&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;数据库表与它生成的实体对象名&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;来观察一下LLBL Gen提供的数据访问接口类型DataAccessAdapter，这提供一个保护的方法成员GetFieldPersistenceInfos，使用Reflector得到它的源代码跟踪进去，看到有数个方法&lt;/p&gt;&lt;span class="rem"&gt;// Summary:&lt;/span&gt;&lt;span class="rem"&gt; Retrieves the persistence info for the field passed in.&lt;/span&gt;&lt;br/&gt;&lt;span class="rem"&gt;// Parameters:&lt;/span&gt;&lt;br/&gt;&lt;span class="rem"&gt;//   field:&lt;/span&gt;&lt;span class="rem"&gt; Field which fieldpersistence info has to be retrieved&lt;/span&gt;&lt;br/&gt;&lt;span class="rem"&gt;// Returns:&lt;/span&gt;&lt;span class="rem"&gt;the requested persistence information&lt;/span&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; IFieldPersistenceInfo GetFieldPersistenceInfo(IEntityField2 field);&lt;br/&gt;&lt;span class="rem"&gt;// Summary: &lt;/span&gt;&lt;span class="rem"&gt;Retrieves the persistence info objects for the fields of the entity passed&lt;/span&gt;&lt;span class="rem"&gt; in.&lt;/span&gt;&lt;br/&gt;&lt;span class="rem"&gt;// Parameters: &lt;/span&gt;&lt;span class="rem"&gt;entity:&lt;/span&gt;&lt;br/&gt;&lt;span class="rem"&gt;//  Entity bject which fields the persistence information should be retrieved &lt;/span&gt;&lt;span class="rem"&gt;for&lt;/span&gt;&lt;br/&gt;&lt;span class="rem"&gt;// Returns:&lt;/span&gt;&lt;span class="rem"&gt;  the requested persistence information&lt;br /&gt;&lt;/span&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; IFieldPersistenceInfo[] GetFieldPersistenceInfos(IEntity2 entity);&lt;br/&gt;&lt;span class="rem"&gt;// Summary: &lt;/span&gt;&lt;span class="rem"&gt;Retrieves the persistence info for the fields passed in.&lt;/span&gt;&lt;br/&gt;&lt;span class="rem"&gt;// Parameters:&lt;/span&gt;&lt;span class="rem"&gt; fields: &lt;/span&gt;&lt;span class="rem"&gt;Fields for which the persistence info has to be determined&lt;/span&gt;&lt;br/&gt;&lt;span class="rem"&gt;// Returns: &lt;/span&gt;&lt;span class="rem"&gt;the requested persistence information&lt;/span&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; IFieldPersistenceInfo[] GetFieldPersistenceInfos(IEntityFields2 fields);&lt;br/&gt;&lt;span class="rem"&gt;// Summary: &lt;/span&gt;&lt;span class="rem"&gt;Retrieves the persistence info objects for the fields of the entity passe &lt;/span&gt;&lt;span class="rem"&gt;in.&lt;/span&gt;&lt;br/&gt;&lt;span class="rem"&gt;// Parameters: &lt;/span&gt;&lt;span class="rem"&gt;entityName:&lt;/span&gt;&lt;br/&gt;&lt;span class="rem"&gt;//Entity name for entity type which fields the persistence information should &lt;/span&gt;&lt;span class="rem"&gt;be retrieved for&lt;/span&gt;&lt;br/&gt;&lt;span class="rem"&gt;// Returns:&lt;/span&gt;&lt;span class="rem"&gt; the requested persistence information&lt;/span&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; IFieldPersistenceInfo[] GetFieldPersistenceInfos(&lt;span class="kwrd"&gt;string&lt;/span&gt; entityName);&lt;p&gt;IFieldPersistenceInfo就是实体属性对应的数据库字段的映射类型，不过这几个方法都是保护类型的，需要在派生类中访问，如下的代码所示&lt;/p&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; Northwind.DAL&lt;br/&gt;{&lt;br/&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;sealed&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; DataAccessAdapter : Northwind.DAL.DatabaseSpecific.DataAccessAdapter&lt;br/&gt;    { &lt;br/&gt;       &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetSourceTableName(&lt;span class="kwrd"&gt;string&lt;/span&gt; entityType)&lt;br/&gt;        {&lt;br/&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;base&lt;/span&gt;.GetFieldPersistenceInfos(entityType)[0].SourceObjectName;&lt;br/&gt;        }&lt;br/&gt;}&lt;br/&gt;       &lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;因为同一个实体对应的表，表中的所有字段所属的表名肯定是相同的，所以直接取它的第零个字段的SourceObjectName。这样，我们就做到了根据实体的名称，来获取它应对的数据库表名称。在我的Management Console开发工具中，没有直接从DatabaseSpecific.DataAccessAdapter类型派生，这样的方式会产生很多麻烦。每新建一个项目就要派生一个类型出来，这样不符合工具的含义，观察一下生成的文件PersistenceInfoProvider&lt;/p&gt;&lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; PersistenceInfoProviderSingleton&lt;br/&gt;{&lt;br/&gt;        &lt;span class="preproc"&gt;#region&lt;/span&gt; Class Member Declarations&lt;br/&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; IPersistenceInfoProvider _providerInstance = &lt;span class="kwrd"&gt;new&lt;/span&gt; PersistenceInfoProviderCore();&lt;br/&gt;        &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;Dummy static constructor to make sure threadsafe initialization is performed.&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;static&lt;/span&gt; PersistenceInfoProviderSingleton()&lt;br/&gt;        {&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;Gets the singleton instance of the PersistenceInfoProviderCore&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br/&gt;        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;Instance of the PersistenceInfoProvider.&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; IPersistenceInfoProvider GetInstance()&lt;br/&gt;        {&lt;br/&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; _providerInstance;&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;}&lt;span class="kwrd"&gt;internal&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; PersistenceInfoProviderCore : PersistenceInfoProviderBase&lt;br/&gt;{&lt;br/&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;Initializes a new instance of the &amp;lt;see cref=&amp;quot;PersistenceInfoProviderCore&amp;quot;/&amp;gt; class.&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;internal&lt;/span&gt; PersistenceInfoProviderCore()&lt;br/&gt;        {&lt;br/&gt;            Init();&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;Method which initializes the internal datastores with the structure of hierarchical types.&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Init()&lt;br/&gt;        {&lt;br/&gt;            &lt;span class="kwrd"&gt;this&lt;/span&gt;.InitClass((13 + 2));&lt;br/&gt;            InitCategoryEntityMappings();&lt;br/&gt;            InitCustomerEntityMappings();    &lt;br/&gt;        }}&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;这两个类型暴露了IPersistenceInfoProvider 给外部类型库来获取它的映射关系，这一点我是通过分析LLBL Gen ORM Support Classes得到的。因为LLBL Gen框架要自动生成SQL语句，必然需要一种机制或是映射来保存这种数据库表和实体的映射关系，NHibernate是使用外部xml配置文件的方式，LLBL Gen则直接使有代码，并且代码直接由生成工具维护，不需要开发人员参与，这一点应该比NHibernate更加合理优秀一些。来看一下经过反射后的得到的代码&lt;/p&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;abstract&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; PersistenceInfoProviderBase : IPersistenceInfoProvider&lt;br/&gt;{&lt;br/&gt;        &lt;span class="kwrd"&gt;protected&lt;/span&gt; PersistenceInfoProviderBase();&lt;br/&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; AddElementFieldMapping(&lt;span class="kwrd"&gt;string&lt;/span&gt; elementName, &lt;span class="kwrd"&gt;string&lt;/span&gt; elementFieldName, &lt;span class="kwrd"&gt;string&lt;/span&gt; sourceColumnName, &lt;span class="kwrd"&gt;bool&lt;/span&gt; isSourceColumnNullable, &lt;span class="kwrd"&gt;string&lt;/span&gt; sourceColumnDbType, &lt;span class="kwrd"&gt;int&lt;/span&gt; sourceColumnMaxLength, &lt;span class="kwrd"&gt;byte&lt;/span&gt; sourceColumnScale, &lt;span class="kwrd"&gt;byte&lt;/span&gt; sourceColumnPrecision, &lt;span class="kwrd"&gt;bool&lt;/span&gt; isIdentity, &lt;span class="kwrd"&gt;string&lt;/span&gt; identityValueSequenceName, TypeConverter typeConverterToUse, Type actualDotNetType, &lt;span class="kwrd"&gt;int&lt;/span&gt; fieldIndex);&lt;br/&gt;        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; AddElementMapping(&lt;span class="kwrd"&gt;string&lt;/span&gt; elementName, &lt;span class="kwrd"&gt;string&lt;/span&gt; catalogName, &lt;span class="kwrd"&gt;string&lt;/span&gt; schemaName, &lt;span class="kwrd"&gt;string&lt;/span&gt; targetName, &lt;span class="kwrd"&gt;int&lt;/span&gt; numberOfFields);&lt;br/&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; IFieldPersistenceInfo[] GetAllFieldPersistenceInfos(IEntity2 entity);&lt;br/&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; IFieldPersistenceInfo[] GetAllFieldPersistenceInfos(&lt;span class="kwrd"&gt;string&lt;/span&gt; elementName);&lt;br/&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; IFieldPersistenceInfo GetFieldPersistenceInfo(&lt;span class="kwrd"&gt;string&lt;/span&gt; elementName, &lt;span class="kwrd"&gt;string&lt;/span&gt; fieldName);&lt;br/&gt;        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; InitClass(&lt;span class="kwrd"&gt;int&lt;/span&gt; capacity);&lt;br/&gt;}&lt;p&gt;方法AddElementMapping和AddElementFieldMapping添加表及其字段与实体的映射到内部集合中，并通过GetAllFieldPersistenceInfos接口向外公布映射数据。这就解释了方法GetSourceTableName的原理。&lt;/p&gt;&lt;p&gt;Management Console因为要适应新项目的需要，所以不能直接用派生的方式，直接用反射来获取元数据信息。&lt;/p&gt;&lt;p&gt;1 反射项目root namespace名称，得到DatabaseSpecific.PersistenceInfoProviderSingleton类型，反射它的GetInstance()方法得到IPersistenceInfoProvider &lt;/p&gt;&lt;p&gt;2 传入需要的参数，得到IFieldPersistenceInfo类型，观察它的属性，可以看到SourceObjectName，其它的属性如下&lt;/p&gt; &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IFieldPersistenceInfo&lt;br/&gt; {&lt;br/&gt;        Type ActualDotNetType { get; }&lt;br/&gt;        &lt;span class="kwrd"&gt;string&lt;/span&gt; IdentityValueSequenceName { get; }&lt;br/&gt;        &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsIdentity { get; }&lt;br/&gt;        &lt;span class="kwrd"&gt;string&lt;/span&gt; SourceCatalogName { get; }&lt;br/&gt;        &lt;span class="kwrd"&gt;string&lt;/span&gt; SourceColumnDbType { get; }&lt;br/&gt;        &lt;span class="kwrd"&gt;bool&lt;/span&gt; SourceColumnIsNullable { get; }&lt;br/&gt;        &lt;span class="kwrd"&gt;int&lt;/span&gt; SourceColumnMaxLength { get; }&lt;br/&gt;        &lt;span class="kwrd"&gt;string&lt;/span&gt; SourceColumnName { get; }&lt;br/&gt;        &lt;span class="kwrd"&gt;byte&lt;/span&gt; SourceColumnPrecision { get; }&lt;br/&gt;        &lt;span class="kwrd"&gt;byte&lt;/span&gt; SourceColumnScale { get; }&lt;br/&gt;        &lt;span class="kwrd"&gt;string&lt;/span&gt; SourceObjectName { get; }&lt;br/&gt;        &lt;span class="kwrd"&gt;string&lt;/span&gt; SourceSchemaName { get; }&lt;br/&gt;        TypeConverter TypeConverterToUse { get; }&lt;br/&gt;}&lt;p&gt;这些属性的含义，就代表了数据库字段的内存映射，于DataTable不同。DataTable是装载数据，而IFieldPersistenceInfo是装载字段的元数据，也就是下图中的Column Properties&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/201112270930205580.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/201112270930217249.png" width="784" height="466" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;这个类型在生成SQL语句方面有重要的作用，你可以通过查看它的源代码（反射得到，没有加密）看到它的重要作用。&lt;/p&gt;&lt;p&gt;讲到这里，所有的元数据的信息都可以通过上面的接口和方法获取到。   &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;SQL Trace &lt;/strong&gt;&lt;/p&gt;&lt;p&gt;如果对LLBL Gen生成的SQL语句感兴趣，可以通过Trace机制来跟踪它的SQL输出，配置过程如下所示。修改配置文件&lt;/p&gt;&amp;lt;system.diagnostics&amp;gt;&lt;br/&gt;        &amp;lt;!-- LLBLGen Trace&lt;br/&gt;            Trace Level:    0 - Disabled&lt;br/&gt;                            3 - Info&lt;br/&gt;                            4 - Verbose&lt;br/&gt;        &amp;lt;switches&amp;gt;&lt;br/&gt;            &amp;lt;add name=&lt;span class="str"&gt;&amp;quot;SqlServerDQE&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;value&lt;/span&gt;=&lt;span class="str"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; /&amp;gt;&lt;br/&gt;            &amp;lt;add name=&lt;span class="str"&gt;&amp;quot;ORMGeneral&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;value&lt;/span&gt;=&lt;span class="str"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; /&amp;gt;&lt;br/&gt;            &amp;lt;add name=&lt;span class="str"&gt;&amp;quot;ORMStateManagement&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;value&lt;/span&gt;=&lt;span class="str"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; /&amp;gt;&lt;br/&gt;            &amp;lt;add name=&lt;span class="str"&gt;&amp;quot;ORMPersistenceExecution&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;value&lt;/span&gt;=&lt;span class="str"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; /&amp;gt;&lt;br/&gt;        &amp;lt;/switches&amp;gt;&lt;br/&gt;        &amp;lt;trace autoflush=&lt;span class="str"&gt;&amp;quot;true&amp;quot;&lt;/span&gt;&amp;gt;&lt;br/&gt;            &amp;lt;listeners&amp;gt;&lt;br/&gt;                &amp;lt;add name=&lt;span class="str"&gt;&amp;quot;textWriterTraceListener&amp;quot;&lt;/span&gt;&lt;br/&gt;                     type=&lt;span class="str"&gt;&amp;quot;System.Diagnostics.TextWriterTraceListener&amp;quot;&lt;/span&gt;&lt;br/&gt;                     initializeData=&lt;span class="str"&gt;&amp;quot;D:\\erp solution\esolution_log.txt&amp;quot;&lt;/span&gt; /&amp;gt;&lt;br/&gt;            &amp;lt;/listeners&amp;gt;&lt;br/&gt;        &amp;lt;/trace&amp;gt;&lt;br/&gt;        --&amp;gt;&lt;br/&gt;    &amp;lt;/system.diagnostics&amp;gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;这样配置，可以将LLBL Gen生成的SQL语句输出到文本文件中，不过这种方式不适合即时查看。需要重写一个TraceListener来截获它的SQL输出。&lt;/p&gt; &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ORMTraceListener : TraceListener&lt;br/&gt;    {&lt;br/&gt;        &lt;span class="kwrd"&gt;static&lt;/span&gt; Socket m_socClient;&lt;br/&gt;        &lt;span class="rem"&gt;//在可以连接的情况下，才能保证去发送消息&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; m_serverAvailable=&lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br/&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;static&lt;/span&gt; ORMTraceListener()&lt;br/&gt;        {&lt;br/&gt;            m_server = &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br/&gt;            OnConnect(&lt;span class="str"&gt;&amp;quot;127.0.0.1&amp;quot;&lt;/span&gt;, 2907);&lt;br/&gt;        }&lt;br/&gt;      &lt;br/&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Write(&lt;span class="kwrd"&gt;string&lt;/span&gt; message)&lt;br/&gt;        {&lt;br/&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (!String.IsNullOrEmpty(message) &amp;amp;&amp;amp; m_server&amp;amp;&amp;amp;NeedSend(message))&lt;br/&gt;                OnSendData(message);&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; WriteLine(&lt;span class="kwrd"&gt;string&lt;/span&gt; message)&lt;br/&gt;        {&lt;br/&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (!String.IsNullOrEmpty(message) &amp;amp;&amp;amp; m_server &amp;amp;&amp;amp; NeedSend(message))&lt;br/&gt;                OnSendData(message+Environment.NewLine);&lt;br/&gt;        }&lt;br/&gt;}&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;这里应用Socket把截取的SQL语句输出到我的监控程序中，修改上面的type为ORMTraceListener 即可。&lt;/p&gt;&lt;p&gt;截取的SQL语句不是标准的SQL Server语句。原因是LLBL Gen是跨数据库平台的，独立于数据库方言，所以要用一种公共的方法来描述生成的SQL语句，这也提供了一种通用SQL语句生成的方法(学技术的同时，也看到了技术的最佳实践，这在以后的工作中会提供相当大的帮助）。SQL语句格式如下所示&lt;/p&gt;Generated &lt;span class="kwrd"&gt;Sql&lt;/span&gt; query: &lt;br/&gt;&lt;br/&gt;    Query: &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; &lt;span class="kwrd"&gt;DISTINCT&lt;/span&gt; [Enterprise].[dbo].[Company].[CompanyCode] &lt;span class="kwrd"&gt;FROM&lt;/span&gt; [Enterprise].[dbo].[Company]       &lt;span class="kwrd"&gt;WHERE&lt;/span&gt; ( ( [Enterprise].[dbo].[Company].[Suspended] = @Suspended1)) &lt;span class="kwrd"&gt;ORDER&lt;/span&gt; &lt;span class="kwrd"&gt;BY&lt;/span&gt;          [Enterprise].[dbo].[Company].[CompanyCode] &lt;span class="kwrd"&gt;ASC&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;Parameter&lt;/span&gt;: @Suspended1 : String. Length: 1. &lt;span class="kwrd"&gt;Precision&lt;/span&gt;: 0. Scale: 0. Direction: &lt;span class="kwrd"&gt;Input&lt;/span&gt;. &lt;span class="kwrd"&gt;Value&lt;/span&gt;: &amp;quot;N&amp;quot;.&lt;p&gt;在此基础上，再创建一个解析工具，把这里的SQL解析成可以直接在SQL Server中运行的T-SQL脚本。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/JamesLi2015/aggbug/2303020.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/JamesLi2015/archive/2011/12/27/2303020.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/JamesLi2015/archive/2011/12/26/2301530.html</id><title type="text">ORM + .NET Remoting 完整例子程序 虽然现在都流行WCF，也没有必要抛弃已经掌握的.NET Remoting</title><summary type="text">LLBL Gen作为项目开发的ORM框架，选择.NET Remoting作为分布式技术框架。一直也很想把ERP框架从.NET Remoting升级到WCF，只是关于方法重载的配置方法需要特殊处理。举例说明如下 public interface IEmployeeManager{ EmployeeEntity GetEmployee(System.Int32 Employeeid);...</summary><published>2011-12-26T01:04:00Z</published><updated>2011-12-26T01:04:00Z</updated><author><name>James Li</name><uri>http://www.cnblogs.com/JamesLi2015/</uri></author><link rel="alternate" href="http://www.cnblogs.com/JamesLi2015/archive/2011/12/26/2301530.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/JamesLi2015/archive/2011/12/26/2301530.html"/><content type="html">&lt;p&gt;LLBL Gen作为项目开发的ORM框架，选择.NET Remoting作为分布式技术框架。一直也很想把ERP框架从.NET Remoting升级到WCF，只是关于方法重载的配置方法需要特殊处理。举例说明如下&lt;/p&gt;  &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IEmployeeManager&lt;br/&gt;{&lt;br/&gt;        EmployeeEntity GetEmployee(System.Int32 Employeeid);&lt;br/&gt;        EmployeeEntity GetEmployee(System.Int32 Employeeid, IPrefetchPath2 prefetchPath);&lt;br/&gt;        EmployeeEntity GetEmployee(System.Int32 Employeeid, IPrefetchPath2 prefetchPath,  ExcludeIncludeFieldsList fieldList);&lt;br/&gt;}&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;IEmployeeManager接口用于对员工表Employee进行CRUD操作。上面三个重载方法是用来从数据库中读取员工信息&lt;/p&gt;&lt;p&gt;对.NET Remoting技术实现，只需要派生于MarshalByRefObject，实现IEmployeeManager接口的方法即可&lt;/p&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; EmployeeManager : MarshalByRefObject, IEmployeeManager&lt;br/&gt;{&lt;br/&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; EmployeeEntity GetEmployee(System.Int32 Employeeid)&lt;br/&gt;        {&lt;br/&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; GetEmployee(Employeeid, &lt;span class="kwrd"&gt;null&lt;/span&gt;);&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; EmployeeEntity GetEmployee(System.Int32 Employeeid, IPrefetchPath2 prefetchPath)&lt;br/&gt;        {&lt;br/&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; GetEmployee(Employeeid, prefetchPath, &lt;span class="kwrd"&gt;null&lt;/span&gt;);&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; EmployeeEntity GetEmployee(System.Int32 Employeeid, IPrefetchPath2 prefetchPath, ExcludeIncludeFieldsList fieldList)&lt;br/&gt;        {&lt;br/&gt;            EmployeeEntity _Employee = &lt;span class="kwrd"&gt;new&lt;/span&gt; EmployeeEntity(Employeeid);&lt;br/&gt;            &lt;span class="kwrd"&gt;using&lt;/span&gt; (DataAccessAdapterBase adapter = GetCompanyDataAccessAdapter())&lt;br/&gt;            {&lt;br/&gt;                &lt;span class="kwrd"&gt;bool&lt;/span&gt; found = adapter.FetchEntity(_Employee, prefetchPath, &lt;span class="kwrd"&gt;null&lt;/span&gt;, fieldList);&lt;br/&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (!found) &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; RecordNotFoundException(&lt;span class="str"&gt;&amp;quot;Invalid Employee&amp;quot;&lt;/span&gt;);&lt;br/&gt;            }&lt;br/&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; _Employee;&lt;br/&gt;        }&lt;br/&gt;}&lt;p&gt;这样对于.NET Remoting是没有问题的。然后对于WCF技术，它不支持方法重载overload，需要添加Name特性&lt;/p&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IEmployeeManager&lt;br/&gt;{&lt;br/&gt;       [OperationContract(Name=&lt;span class="str"&gt;&amp;quot;Employeeid&amp;quot;&lt;/span&gt;)]&lt;br/&gt;       EmployeeEntity GetEmployee(System.Int32 Employeeid);&lt;br/&gt;       [OperationContract(Name=&lt;span class="str"&gt;&amp;quot;EmployeeidPrefetchPath&amp;quot;&lt;/span&gt;)]&lt;br/&gt;       EmployeeEntity GetEmployee(System.Int32 Employeeid, IPrefetchPath2 prefetchPath); &lt;br/&gt;       [OperationContract(Name=&lt;span class="str"&gt;&amp;quot;EmployeeidPrefetchPathFieldList&amp;quot;&lt;/span&gt;)]&lt;br/&gt;       EmployeeEntity GetEmployee(System.Int32 Employeeid, IPrefetchPath2 prefetchPath,  ExcludeIncludeFieldsList fieldList);&lt;br/&gt;}&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;每次加这么多参数很麻烦，于是就制造一个工具，专门用于生成Name的参数值&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/20111226090418572.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/201112260904192557.png" width="784" height="212" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;甚至可以把这个工具的代码直接集成到Code Smith的模板中，这样大大减少了工作量，提高工作效率。&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;回到主题，来看看LLBL Gen的.NET Remoting版本，这个例子被直接映射到了ERP框架中。&lt;/p&gt;&lt;p&gt;定义接口方法&lt;/p&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IService&lt;br/&gt;{       &lt;br/&gt;     &lt;span class="kwrd"&gt;int&lt;/span&gt; GetNumberOfCustomers();&lt;br/&gt;     &lt;span class="kwrd"&gt;void&lt;/span&gt; GetOrderStatistics(&lt;span class="kwrd"&gt;out&lt;/span&gt; &lt;span class="kwrd"&gt;decimal&lt;/span&gt; averageOrderPrice, &lt;span class="kwrd"&gt;out&lt;/span&gt; &lt;span class="kwrd"&gt;decimal&lt;/span&gt; highestOrderPrice,                              &lt;span class="kwrd"&gt;out&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; numberOfOrders, &lt;span class="kwrd"&gt;out&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; orderIdWithHighestPrice);&lt;br/&gt;     OrderEntity GetOrderAndCustomerWithHighestPrice(&lt;span class="kwrd"&gt;int&lt;/span&gt; orderId);&lt;br/&gt;     CustomerEntity GetCustomerWithMostOrdersAndNumberOfOrders(&lt;span class="kwrd"&gt;out&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; numberOfOrders);&lt;br/&gt;     EntityCollection&amp;lt;CustomerEntity&amp;gt; GetAllCustomers();&lt;br/&gt;     EntityCollection&amp;lt;CustomerEntity&amp;gt; GetAllCustomersFilteredOnProduct(&lt;span class="kwrd"&gt;int&lt;/span&gt; productId);&lt;br/&gt;     EntityCollection&amp;lt;ProductEntity&amp;gt; GetProductsSortedBySortExpression(SortExpression sorter);        &lt;br/&gt;     &lt;span class="kwrd"&gt;bool&lt;/span&gt; RemoveOrder(OrderEntity toRemove);&lt;br/&gt;     CustomerEntity GetCustomerWithFullOrders(&lt;span class="kwrd"&gt;string&lt;/span&gt; customerId);&lt;br/&gt;     &lt;span class="kwrd"&gt;bool&lt;/span&gt; SaveCustomer(CustomerEntity toSave, &lt;span class="kwrd"&gt;bool&lt;/span&gt; recursive);&lt;br/&gt;     CustomerEntity GetCustomer(&lt;span class="kwrd"&gt;string&lt;/span&gt; customerId);&lt;br/&gt;     &lt;span class="kwrd"&gt;void&lt;/span&gt; SaveOrders(EntityCollection&amp;lt;OrderEntity&amp;gt; orders);&lt;br/&gt;}&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;从技术的角度来讲，有二种类型的方法：单向的，传入参数，执行动作，不返回值；双工，传入参数，返回值。&lt;/p&gt;&lt;p&gt;接口的实现代码&lt;/p&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Service : MarshalByRefObject, IService&lt;br/&gt;{&lt;br/&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; GetNumberOfCustomers()&lt;br/&gt;    {&lt;br/&gt;       Console.WriteLine(&lt;span class="str"&gt;&amp;quot;GetNumberOfCustomers called&amp;quot;&lt;/span&gt;);&lt;br/&gt;       &lt;span class="kwrd"&gt;using&lt;/span&gt;(DataAccessAdapter adapter = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataAccessAdapter())&lt;br/&gt;       {&lt;br/&gt;            &lt;span class="rem"&gt;// simply obtain the count of the customerid and return that.&lt;/span&gt;&lt;br/&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt;)adapter.GetScalar(CustomerFields.CustomerId, AggregateFunction.CountRow);&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;}&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;其它的代码参考下载的例子程序，它的实现代码可以用代码生成器生成。不带参数的DataAccessAdapter 表示从默认生成的配置文件中读取连接字符串，内容如下&lt;/p&gt;&amp;lt;?xml version=&lt;span class="str"&gt;&amp;quot;1.0&amp;quot;&lt;/span&gt; encoding=&lt;span class="str"&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt; ?&amp;gt;&lt;br/&gt;&amp;lt;configuration&amp;gt;&lt;br/&gt;    &amp;lt;appSettings&amp;gt;&lt;br/&gt;        &amp;lt;add key=&lt;span class="str"&gt;&amp;quot;Northwind.ConnectionString.SQL Server (SqlClient)&amp;quot;&lt;/span&gt; &lt;span class="kwrd"&gt;value&lt;/span&gt;=&lt;span class="str"&gt;&amp;quot;data source=.\sqlexpress;initial  &lt;/span&gt;&lt;span class="str"&gt;                  catalog=Northwind;integrated security=SSPI;persist security info=False;packet size=4096&amp;quot;&lt;/span&gt;/&amp;gt;&lt;br/&gt;    &amp;lt;/appSettings&amp;gt;&lt;br/&gt;&amp;lt;/configuration&amp;gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;服务器端的实现，把接口的实现代码发布成服务&lt;/p&gt;&lt;span class="rem"&gt;// register a channel and assign the service type to it. This opens the service to the outside world at TCP port 65100.&lt;/span&gt;&lt;br/&gt;TcpChannel channel = &lt;span class="kwrd"&gt;new&lt;/span&gt; TcpChannel(65100);&lt;br/&gt;ChannelServices.RegisterChannel(channel, &lt;span class="kwrd"&gt;true&lt;/span&gt;);&lt;br/&gt;&lt;br/&gt;Type serverType = Type.GetType(&lt;span class="str"&gt;&amp;quot;RemotingService.Service&amp;quot;&lt;/span&gt;);&lt;br/&gt;RemotingConfiguration.RegisterWellKnownServiceType(serverType, &lt;span class="str"&gt;&amp;quot;theEndPoint&amp;quot;&lt;/span&gt;, WellKnownObjectMode.Singleton);&lt;br/&gt;&lt;br/&gt;&lt;span class="rem"&gt;// switch on FastSerialization&lt;/span&gt;&lt;br/&gt;SerializationHelper.Optimization = SerializationOptimization.Fast;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;客户端实现代码，读取服务并调用它来实现数据库的读写&lt;/p&gt;&lt;span class="rem"&gt;// grab service object first.             &lt;/span&gt;&lt;br/&gt;TcpChannel channel = &lt;span class="kwrd"&gt;new&lt;/span&gt; TcpChannel();&lt;br/&gt;ChannelServices.RegisterChannel(channel, &lt;span class="kwrd"&gt;true&lt;/span&gt;);&lt;br/&gt;&lt;br/&gt;MarshalByRefObject o = (MarshalByRefObject)RemotingServices.Connect(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(IService), &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(                        &lt;span class="str"&gt;&amp;quot;tcp://{0}:65100/theEndPoint&amp;quot;&lt;/span&gt;, SERVERNAME));&lt;br/&gt;IService service = o &lt;span class="kwrd"&gt;as&lt;/span&gt; IService;&lt;br/&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt;(service == &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br/&gt;{&lt;br/&gt;      &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; Exception(&lt;span class="str"&gt;&amp;quot;Service couldn't be obtained. Aborting&amp;quot;&lt;/span&gt;);&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;MainForm.DalService = service;&lt;br/&gt;&lt;span class="rem"&gt;// switch on FastSerialization&lt;/span&gt;&lt;br/&gt;SerializationHelper.Optimization = SerializationOptimization.Fast;&lt;p&gt;之后的代码中，都会应用MainForm.DalService来获取客户数据以及客户的产品资料。&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;这个例子还有几点可以讨论的地方，请参考如下的思考&lt;/p&gt;&lt;p&gt;1&amp;#160; 服务的调用代码。如果有多个.NET Remoting服务 ，应该做成工厂模式，并且提高cache以减少内存的消耗。&lt;/p&gt;&lt;p&gt;工厂模式的参考代码如下所示&lt;/p&gt;IService service;&lt;br/&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt;(!_cache.Contains(service))&lt;br/&gt;  service=CreateService(service)&lt;br/&gt;&lt;span class="kwrd"&gt;return&lt;/span&gt; service;&amp;#160;&lt;p&gt;这样实现的好处是，当这个接口被多个客户段代码调用时，服务实现只被创建了一次，节约内存。虽然.NET的垃圾回收器已经很智能了，但是这种带缓存版本的写法，比没有缓存要有效率。   &lt;br /&gt;&lt;/p&gt;&lt;p&gt;2&amp;#160; 没有使用配置文件，而是直接在代码中创建TcpChannel的方式。在学.NET Remoting的时，也喜欢用各种书中推荐的方式，用配置文件而不是直接硬编码到代码中。在实践中发现，这样每次都需要把已经配置好的配置文件的片段拷贝到新项目的配置文件中，比较麻烦。一般来说，Channel和Port在部署到客户服务器上是不会变动的。于是就改变做法，把Channel的创建直接写到代码中，Port留给配置文件来指定。这种方式不需要增加配置文件节，方便部署。   &lt;br /&gt;&lt;/p&gt;&lt;p&gt;3 当方法需要返回多个值时，参考接口IService的GetOrderStatistics方法，这里使用的是out修饰参数。把值赋给传入的参数，方法调用完成后，再获取参数值。这里，推荐用结构struct设计成返回值，以应对增加参数的变化。&lt;/p&gt;&lt;p&gt;方法参数的传入也一样，当有多个参数要传入到方法内部时，可以有struct把这些参数简单封装一下，作为一个整体传入方法中。在未来有对这个方法进入维护时，也会相对容易一些。&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;文章中提到的例子程序，请到LLBL Gen官方网站下载，代码名称是Example_NorthwindRemotingExampleCS_Adapter。&lt;/p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&amp;#160;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;img src="http://www.cnblogs.com/JamesLi2015/aggbug/2301530.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/JamesLi2015/archive/2011/12/26/2301530.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/JamesLi2015/archive/2011/12/23/2299837.html</id><title type="text">ERP项目开发中的DataTable的性能优化 代码写得漂亮看起来舒服，运行起来也有效率</title><summary type="text">公司的ERP框架是用ORM技术来访问数据库的，但有些查询还是会用DataTable保存数据，并且会把用户修改后的数据保存到服务器中。在习惯了ORM的写法后，对于用DataTable的保存用户修改过的数据，然后保存到数据库中反而有些不适应。ORM会自动检测到哪些数据项被改动了，进而生成必要的UPDATE子句，如果没有数据被更改，则不会产生任何UPDATE语句，这是ORM的好处与便利。把这个技巧应用到...</summary><published>2011-12-23T09:59:00Z</published><updated>2011-12-23T09:59:00Z</updated><author><name>James Li</name><uri>http://www.cnblogs.com/JamesLi2015/</uri></author><link rel="alternate" href="http://www.cnblogs.com/JamesLi2015/archive/2011/12/23/2299837.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/JamesLi2015/archive/2011/12/23/2299837.html"/><content type="html">&lt;p&gt;公司的ERP框架是用ORM技术来访问数据库的，但有些查询还是会用DataTable保存数据，并且会把用户修改后的数据保存到服务器中。在习惯了ORM的写法后，对于用DataTable的保存用户修改过的数据，然后保存到数据库中反而有些不适应。ORM会自动检测到哪些数据项被改动了，进而生成必要的UPDATE子句，如果没有数据被更改，则不会产生任何UPDATE语句，这是ORM的好处与便利。把这个技巧应用到DataTable中，来看看下面的性能优化技巧。&lt;/p&gt;  DataColumn item = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataColumn(&lt;span class="str"&gt;&amp;quot;IsChanged&amp;quot;&lt;/span&gt;, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;bool&lt;/span&gt;));&lt;br/&gt;item.DefaultValue = &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br/&gt;itemTable.Columns.Add(item);&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;有一个临时的查询表itemTable，保存物料的计划信息。在物料计划功能中，我们会修改一下物料的计划数据，然后把它保存到数据库中。因为有很多物料，有的会被修改计划日期，有的不会修改，所以我给物料计划表itemTable加了一个额外的字段IsChanged，以表示这个物料的物料计划是否被修改过。如果被修改过，比如下面的方法&lt;/p&gt;itemTable.Rows[0][&lt;span class="str"&gt;&amp;quot;PlanQty&amp;quot;&lt;/span&gt;]=200;&lt;br/&gt;itemTable.Rows[0][&lt;span class="str"&gt;&amp;quot;IsChanged&amp;quot;&lt;/span&gt;]=&lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;第二行代码，我会把这个table的IsChange列的值设为true，表示这一行已经被修改过，在保存时，需要生成SQL UPDATE语句。这样，在窗体被关闭时或用户点击保存按钮时，用下面的判断语句&lt;/p&gt;&lt;span class="kwrd"&gt;int&lt;/span&gt; changed=(from item &lt;span class="kwrd"&gt;in&lt;/span&gt; itemTable.AsEnumerable()&lt;br/&gt;                    &lt;span class="kwrd"&gt;where&lt;/span&gt; item.Fields&amp;lt;&lt;span class="kwrd"&gt;bool&lt;/span&gt;&amp;gt;(&lt;span class="str"&gt;&amp;quot;IsChanged&amp;quot;&lt;/span&gt;)==&lt;span class="kwrd"&gt;true&lt;/span&gt;&lt;br/&gt;                    selectg item).Count();&lt;br/&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt;(changed)&lt;br/&gt;{&lt;br/&gt;       &lt;span class="kwrd"&gt;foreach&lt;/span&gt;(item &lt;span class="kwrd"&gt;in&lt;/span&gt;  itemTable.AsEnumerable()&lt;br/&gt;                                 &lt;span class="kwrd"&gt;where&lt;/span&gt; item.Fields&amp;lt;&lt;span class="kwrd"&gt;bool&lt;/span&gt;&amp;gt;(&lt;span class="str"&gt;&amp;quot;IsChanged&amp;quot;&lt;/span&gt;)==&lt;span class="kwrd"&gt;true&lt;/span&gt;)&lt;br/&gt;       &lt;span class="rem"&gt;//save item and its plan qty&lt;/span&gt;&lt;br/&gt;}&lt;p&gt;changed变量判断当前是否有物料的计划数量被更改过，如果有才保存被改过的物料及其计划，否则不会做任何动作。&lt;/p&gt;&lt;p&gt;以此类推，这个技巧还可以应用于删除或是新增&lt;/p&gt;DataColumn item = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataColumn(&lt;span class="str"&gt;&amp;quot;IsNew&amp;quot;&lt;/span&gt;, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;bool&lt;/span&gt;));&lt;br/&gt;item.DefaultValue = &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br/&gt;itemTable.Columns.Add(item);&lt;br/&gt;&lt;br/&gt;item = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataColumn(&lt;span class="str"&gt;&amp;quot;IsDeleted&amp;quot;&lt;/span&gt;, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;bool&lt;/span&gt;));&lt;br/&gt;item.DefaultValue = &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br/&gt;itemTable.Columns.Add(item);&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;虽然这是个很小的技巧，却可以解决很多场合的问题。举例说明&lt;/p&gt;&lt;p&gt;1 用户打开物料计划功能，只是看了一下，没有修改任何物料及其计划，在退出功能时，你不应该提示用户保存，因为用户没有作任何数据修改动作。&lt;/p&gt;&lt;p&gt;2 用户新增加了一条物料及其计划，你可以判断是新加的，进而生产INSERT语句，而不是UPDATE语句。如果不用这个技巧，你需要到数据库中去判断是否有这个物料的计划数据，如果有则产生UPDATE语句，否则产生INSERT语句。应用我说的这个技巧(IsNew)，你可以明显的减少往返于数据库之间的逻辑，性能会有明显的改善。&lt;/p&gt;&lt;p&gt;3 用户删除了一条物料及其计划，itemTable少了一行，你怎么把它写回到数据库中去呢？应用这个IsDeleted技巧，不对itemTable调用DeleteRow方法，而是把它的IsDeleted设为true,表示这个物料的计划被删除了，需要产生DELETE语句发送到数据库中。&lt;/p&gt;&lt;p&gt;在判断itemTable是否被修改过，也可以应用这个技巧&lt;/p&gt;&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (DataRow row &lt;span class="kwrd"&gt;in&lt;/span&gt; itemTable.Rows)&lt;br/&gt;{&lt;br/&gt;         &lt;span class="kwrd"&gt;if&lt;/span&gt; (row.RowState == DataRowState.Unchanged)&lt;br/&gt;                    &lt;span class="kwrd"&gt;continue&lt;/span&gt;;&lt;br/&gt;         &lt;span class="rem"&gt;//save changed item and its plan qty&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;}&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;DataRow有一个RowState属性，以表示这个表是否被修改过。你可以不用加上面的IsChanged列而应用RowState来判断，也可以达到这个目的。DataRowState.Added 表示是新增加的一行数据，其它的值是&lt;/p&gt;&lt;span class="rem"&gt;// Summary:&lt;/span&gt;&lt;br/&gt;&lt;span class="rem"&gt;//Gets the state of a System.Data.DataRow object.&lt;/span&gt;&lt;br/&gt;[Flags]&lt;br/&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;enum&lt;/span&gt; DataRowState&lt;br/&gt;{&lt;br/&gt;        &lt;span class="rem"&gt;// Summary:&lt;/span&gt;&lt;br/&gt;        &lt;span class="rem"&gt;//     The row has been created but is not part of any System.Data.DataRowCollection.&lt;/span&gt;&lt;br/&gt;        &lt;span class="rem"&gt;//     A System.Data.DataRow is in this state immediately after it has been created&lt;/span&gt;&lt;br/&gt;        &lt;span class="rem"&gt;//     and before it is added to a collection, or if it has been removed from a&lt;/span&gt;&lt;br/&gt;        &lt;span class="rem"&gt;//     collection.&lt;/span&gt;&lt;br/&gt;        Detached = 1,&lt;br/&gt;        &lt;span class="rem"&gt;//&lt;/span&gt;&lt;br/&gt;        &lt;span class="rem"&gt;// Summary:&lt;/span&gt;&lt;br/&gt;        &lt;span class="rem"&gt;//     The row has not changed since System.Data.DataRow.AcceptChanges() was last&lt;/span&gt;&lt;br/&gt;        &lt;span class="rem"&gt;//     called.&lt;/span&gt;&lt;br/&gt;        Unchanged = 2,&lt;br/&gt;        &lt;span class="rem"&gt;//&lt;/span&gt;&lt;br/&gt;        &lt;span class="rem"&gt;// Summary:&lt;/span&gt;&lt;br/&gt;        &lt;span class="rem"&gt;//     The row has been added to a System.Data.DataRowCollection, and System.Data.DataRow.AcceptChanges()&lt;/span&gt;&lt;br/&gt;        &lt;span class="rem"&gt;//     has not been called.&lt;/span&gt;&lt;br/&gt;        Added = 4,&lt;br/&gt;        &lt;span class="rem"&gt;//&lt;/span&gt;&lt;br/&gt;        &lt;span class="rem"&gt;// Summary:&lt;/span&gt;&lt;br/&gt;        &lt;span class="rem"&gt;//     The row was deleted using the System.Data.DataRow.Delete() method of the&lt;/span&gt;&lt;br/&gt;        &lt;span class="rem"&gt;//     System.Data.DataRow.&lt;/span&gt;&lt;br/&gt;        Deleted = 8,&lt;br/&gt;        &lt;span class="rem"&gt;//&lt;/span&gt;&lt;br/&gt;        &lt;span class="rem"&gt;// Summary:&lt;/span&gt;&lt;br/&gt;        &lt;span class="rem"&gt;//     The row has been modified and System.Data.DataRow.AcceptChanges() has not&lt;/span&gt;&lt;br/&gt;        &lt;span class="rem"&gt;//     been called.&lt;/span&gt;&lt;br/&gt;        Modified = 16,&lt;br/&gt;}&amp;#160;&lt;p&gt;对于Add或Delete的情况，我还是习惯于加IsNew或IsDeleted列，尽管这不是必要的。&lt;/p&gt;&lt;p&gt;在应用ORM框架保存实体时，它会检测实体的字段属性是否被修改，只有修改过的属性，才会出现在ORM框架生成的UPDATE语句中，这样确实有效率，与判断DataTable的列值是否被修改过相似，看似乎一点点的改进，对于系统的性能提升是有好处的。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/JamesLi2015/aggbug/2299837.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/JamesLi2015/archive/2011/12/23/2299837.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/JamesLi2015/archive/2011/12/23/2299304.html</id><title type="text">ORM Querier 基于Transact-SQL解析的代码生成利器 帮助开发人员高效快速生成需要的ORM代码</title><summary type="text">对于习惯于用ORM来开发系统的开发人员来说，几乎不用写SQL语句，但是也要针对ORM框架，来设计合适的查询，ORM框架会生成合适的T_SQL语句并发送到SQL Server中。由于ORM框架有好几种，比如NHibernate,LLBL Gen,Entity Framwork，掌握熟练的SQL查询技术在这里没有用武之地，真是可惜。这篇文章是介绍我的Management Console中的一个工具程序...</summary><published>2011-12-23T05:32:00Z</published><updated>2011-12-23T05:32:00Z</updated><author><name>James Li</name><uri>http://www.cnblogs.com/JamesLi2015/</uri></author><link rel="alternate" href="http://www.cnblogs.com/JamesLi2015/archive/2011/12/23/2299304.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/JamesLi2015/archive/2011/12/23/2299304.html"/><content type="html">&lt;p&gt;对于习惯于用ORM来开发系统的开发人员来说，几乎不用写SQL语句，但是也要针对ORM框架，来设计合适的查询，ORM框架会生成合适的T_SQL语句并发送到SQL Server中。由于ORM框架有好几种，比如NHibernate,LLBL Gen,Entity Framwork，掌握熟练的SQL查询技术在这里没有用武之地，真是可惜。这篇文章是介绍我的Management Console中的一个工具程序，把SQL查询语句转化为ORM代码片段，相当于一个代码生成工具。    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;选定Northwind数据库的客户表为例子，它的脚本是这样的，这里省略了表的约束代码。&lt;/p&gt;  &lt;span class="kwrd"&gt;CREATE&lt;/span&gt; &lt;span class="kwrd"&gt;TABLE&lt;/span&gt; [dbo].[Customers]&lt;br/&gt;(&lt;br/&gt;[CustomerID] [&lt;span class="kwrd"&gt;nchar&lt;/span&gt;] (5) &lt;span class="kwrd"&gt;COLLATE&lt;/span&gt; Chinese_PRC_CI_AS &lt;span class="kwrd"&gt;NOT&lt;/span&gt; &lt;span class="kwrd"&gt;NULL&lt;/span&gt;,&lt;br/&gt;[CompanyName] [nvarchar] (40) &lt;span class="kwrd"&gt;COLLATE&lt;/span&gt; Chinese_PRC_CI_AS &lt;span class="kwrd"&gt;NOT&lt;/span&gt; &lt;span class="kwrd"&gt;NULL&lt;/span&gt;,&lt;br/&gt;[ContactName] [nvarchar] (30) &lt;span class="kwrd"&gt;COLLATE&lt;/span&gt; Chinese_PRC_CI_AS &lt;span class="kwrd"&gt;NULL&lt;/span&gt;,&lt;br/&gt;[ContactTitle] [nvarchar] (30) &lt;span class="kwrd"&gt;COLLATE&lt;/span&gt; Chinese_PRC_CI_AS &lt;span class="kwrd"&gt;NULL&lt;/span&gt;,&lt;br/&gt;[Address] [nvarchar] (60) &lt;span class="kwrd"&gt;COLLATE&lt;/span&gt; Chinese_PRC_CI_AS &lt;span class="kwrd"&gt;NULL&lt;/span&gt;,&lt;br/&gt;[City] [nvarchar] (15) &lt;span class="kwrd"&gt;COLLATE&lt;/span&gt; Chinese_PRC_CI_AS &lt;span class="kwrd"&gt;NULL&lt;/span&gt;,&lt;br/&gt;[Region] [nvarchar] (15) &lt;span class="kwrd"&gt;COLLATE&lt;/span&gt; Chinese_PRC_CI_AS &lt;span class="kwrd"&gt;NULL&lt;/span&gt;,&lt;br/&gt;[PostalCode] [nvarchar] (10) &lt;span class="kwrd"&gt;COLLATE&lt;/span&gt; Chinese_PRC_CI_AS &lt;span class="kwrd"&gt;NULL&lt;/span&gt;,&lt;br/&gt;[Country] [nvarchar] (15) &lt;span class="kwrd"&gt;COLLATE&lt;/span&gt; Chinese_PRC_CI_AS &lt;span class="kwrd"&gt;NULL&lt;/span&gt;,&lt;br/&gt;[Phone] [nvarchar] (24) &lt;span class="kwrd"&gt;COLLATE&lt;/span&gt; Chinese_PRC_CI_AS &lt;span class="kwrd"&gt;NULL&lt;/span&gt;,&lt;br/&gt;[Fax] [nvarchar] (24) &lt;span class="kwrd"&gt;COLLATE&lt;/span&gt; Chinese_PRC_CI_AS &lt;span class="kwrd"&gt;NULL&lt;/span&gt;&lt;br/&gt;) &lt;span class="kwrd"&gt;ON&lt;/span&gt; [&lt;span class="kwrd"&gt;PRIMARY&lt;/span&gt;]&lt;br/&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;现在要开发一个查询客户信息的程序，找出客户ID为ANATR的地址，公司名称和联系人信息&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/201112231331436603.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/20111223133143539.png" width="784" height="206" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;由于使用了LLBL Gen ORM框架作为数据访问技术，上面的SQL语句显然不能直接拼凑成C#代码，需要进行转化，封装&lt;/p&gt;&lt;p&gt;的过程比较相对容易，但是也需要耗费一些时间和精力。来看看我设计代码生成工具ORM Querier&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/201112231331438064.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/201112231331443637.png" width="784" height="420" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;在上面的文本框中输入SQL语句，点击Generate生成按钮，同下面自动生成了C#代码。如果你熟悉LLBL Gen框架的API接口，拷贝这片代码到C#中是可以直接运行的，相当于我们的SQL查询语句的ORM版形式。&lt;/p&gt;&lt;p&gt;目前因为只用到了LLBL Gen，所以它只生成了基于LLBL Gen的代码片段。它的基本原理是解析T_SQL语句，生成映射的C#语句，所以，推广到生成NHibernate或是Entity Framework不是难题。   &lt;br /&gt;  &lt;br /&gt;&lt;/p&gt;&lt;p&gt;这个工具我酝酿了一段时间，一方面要推广自己的EPN快速开发框架，面对大量的不熟悉LLBL Gen这个框架的用户。另一方面，把理论变成代码工具实践，也需要一些技术上的判断与实作。&lt;/p&gt;&lt;p&gt;我在接触LLBL Gen这个ORM框架时，也会经常忘记它的SELECT是如何的写，UPDATE如何写，于是要经常查资料，后来干脆把资料整理出来，打印放到桌子上，经常看一下也不会忘记。如下图所示&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/201112231331443670.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/201112231331446211.png" width="784" height="420" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;这样的工作方法，效率又高了很多。但是也不是每天都会和代码打交道，有时候几个月的时间都是在修改报表，这一块的内容又忘记了。既然是有规律可寻的，就可以探索出合适的工具出来，把规律变成鼠标点击的简单动作，这样大大减少出错的机率，于是就产生了这个工具。试想一下，SQL查询技术，你不会忘记，在熟悉的SQL Server Management Studio中输入要查询的SQL语句，把它拷贝到ORM Querier中，执行Generate转化命令，就得到你需要的ORM代码片段。经过这样的改善，做事的效率又提高了很多，而且准确率高，不会出错。&lt;/p&gt;&lt;p&gt;  &lt;br /&gt;经常地思考如何改善工作效率，把一些规律性的知识和技术转化为软件或程序，经过几年的积累就形成了我的开发工具系列工具集Management Console。我在&lt;a href="http://epn.codeplex.com" target="_blank"&gt;epn.codeplex.com&lt;/a&gt;中开放了一部分的Management Console的源代码，欢迎下载使用，希望能对你的工作和学习有所启发和帮助。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/JamesLi2015/aggbug/2299304.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/JamesLi2015/archive/2011/12/23/2299304.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/JamesLi2015/archive/2011/12/23/2298825.html</id><title type="text">亲自下载CSDN社区600万用户数据 设计两条编程题目考验你的.NET编程基础</title><summary type="text">园子里这两天讨论的比较多的是CSDN-中文IT社区 600万用户数据在互联网上的传播，作为一名技术人员，暂且放下各自的想法的意见，仅仅从技术的角度来讲，分析和考验一下我们的编程基础。把下载到的压缩文件释放到硬盘中，得到文件www.csdn.net.sql。作为技术人员，对这个文件产生好奇心和编程的冲动。于是提出了下面的两条编程题目：1 如何把600万数据导入到SQL Server中？2 如何选择合适的密码加密方法？这个SQL文件有273MB，用SQL Server Management Studio打开它，会产生OutOfMemory异常，用记事本打开也很慢，推荐用Ultra Edit源代码编</summary><published>2011-12-23T01:09:00Z</published><updated>2011-12-23T01:09:00Z</updated><author><name>James Li</name><uri>http://www.cnblogs.com/JamesLi2015/</uri></author><link rel="alternate" href="http://www.cnblogs.com/JamesLi2015/archive/2011/12/23/2298825.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/JamesLi2015/archive/2011/12/23/2298825.html"/><content type="html">&lt;p&gt;园子里这两天讨论的比较多的是CSDN-中文IT社区 600万用户数据在互联网上的传播，作为一名技术人员，暂且放下各自的想法的意见，仅仅从技术的角度来讲，分析和考验一下我们的编程基础。&lt;/p&gt;&lt;p&gt;把下载到的压缩文件释放到硬盘中，得到文件www.csdn.net.sql。作为技术人员，对这个文件产生好奇心和编程的冲动。于是提出了下面的两条编程题目：&lt;/p&gt;&lt;p&gt;&lt;strong&gt;1 如何把600万数据导入到SQL Server中？&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;2 如何选择合适的密码加密方法？&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这个SQL文件有273MB，用SQL Server Management Studio打开它，会产生OutOfMemory异常，用记事本打开也很慢，推荐用Ultra Edit源代码编辑软件打开。&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/201112230908489791.png"&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;估计大家的硬盘里面都有这个文件了，我也就不必给密码和邮件加上阴影了。&lt;/p&gt;&lt;p&gt;用自己曾经注册到的邮件找一下，果然找到了自己的帐号和密码，确实是明文的。&lt;/p&gt;&lt;p&gt;分析一下SQL文件，它是由换行符号分开的，以#分隔用户帐号，密码，电子邮件的格式。这和逗号分隔文件格式很相似，于是动手把它导入到SQL Server中。请参考下面的两行代码&lt;/p&gt;&lt;span class="kwrd"&gt;CREATE&lt;/span&gt; &lt;span class="kwrd"&gt;TABLE&lt;/span&gt; CsdnUser ([&lt;span class="kwrd"&gt;USER&lt;/span&gt;] NVARCHAR(&lt;span class="kwrd"&gt;MAX&lt;/span&gt;) )&lt;br/&gt;  &lt;span class="kwrd"&gt;BULK&lt;/span&gt; INSERT CsdnUser &lt;span class="kwrd"&gt;FROM&lt;/span&gt; N&lt;span class="str"&gt;'F:\www.csdn.net.sql'&lt;/span&gt;&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;然后就是漫长的等待了，在4G内存，4核的Windows 7 x64的机器上，也跑了近5分钟才把数据从文本文件导入到SQL Server的CsdnUser表中。平时喜欢研究性能，性能改善研究，心中一阵窃喜。执行完成后，看到Messages中显示&lt;/p&gt;&lt;p&gt;(6428632 row(s) affected)，果然有600多万行数据，放数据库文件的磁盘一下子耗费了近6G的空间。&lt;/p&gt;&lt;p&gt;跑一下SQL语句 SELECT [User] FROM CsdnUser，用户数据就已经存放到了SQL Server数据库文件中了。&lt;/p&gt;&lt;p&gt;这样完成了文本文件到SQL Server的导入过程。如果我还想进一步的分解每一行的数据，像下面的结果显示这样&lt;/p&gt;&lt;p&gt;SELECT&amp;nbsp; dbo.GetSplitOfIndex(User,'',1) AS [UserId]&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dbo.GetSplitOfIndex(User,'',2) AS [Password]&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;dbo.GetSplitOfIndex(User,'',3) AS [Email]&lt;/p&gt;&lt;p&gt;FROM&amp;nbsp; CsdnUser&lt;/p&gt;&lt;p&gt;则还需要写一个split函数，以分解开用#分开的用户数据。GetSplitOfIndex函数来源于互联网，地址是&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.fengfly.com/plus/view-168590-1.html"&gt;http://www.fengfly.com/plus/view-168590-1.html&lt;/a&gt;， 作者秩名，感谢他的智慧。函数的源代码如下所示&lt;/p&gt;&lt;span class="kwrd"&gt;CREATE&lt;/span&gt; &lt;span class="kwrd"&gt;FUNCTION&lt;/span&gt; [dbo].[GetSplitOfIndex]&lt;br/&gt;(&lt;br/&gt;      @String NVARCHAR(&lt;span class="kwrd"&gt;MAX&lt;/span&gt;) ,  --要分割的字符串&lt;br/&gt;      @split NVARCHAR(10) ,  --分隔符号&lt;br/&gt;      @&lt;span class="kwrd"&gt;index&lt;/span&gt; &lt;span class="kwrd"&gt;INT&lt;/span&gt; --取第几个元素&lt;br/&gt;)&lt;br/&gt;&lt;span class="kwrd"&gt;RETURNS&lt;/span&gt; NVARCHAR(1024)&lt;br/&gt;&lt;span class="kwrd"&gt;AS&lt;/span&gt; &lt;br/&gt;    &lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @location &lt;span class="kwrd"&gt;INT&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @&lt;span class="kwrd"&gt;start&lt;/span&gt; &lt;span class="kwrd"&gt;INT&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @&lt;span class="kwrd"&gt;next&lt;/span&gt; &lt;span class="kwrd"&gt;INT&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @seed &lt;span class="kwrd"&gt;INT&lt;/span&gt;&lt;br/&gt; &lt;br/&gt;        &lt;span class="kwrd"&gt;SET&lt;/span&gt; @String = LTRIM(RTRIM(@String))&lt;br/&gt;        &lt;span class="kwrd"&gt;SET&lt;/span&gt; @&lt;span class="kwrd"&gt;start&lt;/span&gt; = 1&lt;br/&gt;        &lt;span class="kwrd"&gt;SET&lt;/span&gt; @&lt;span class="kwrd"&gt;next&lt;/span&gt; = 1&lt;br/&gt;        &lt;span class="kwrd"&gt;SET&lt;/span&gt; @seed = LEN(@split)&lt;br/&gt;  &lt;br/&gt;        &lt;span class="kwrd"&gt;SET&lt;/span&gt; @location = CHARINDEX(@split, @String)&lt;br/&gt;        &lt;span class="kwrd"&gt;WHILE&lt;/span&gt; @location &amp;lt;&amp;gt; 0&lt;br/&gt;            &lt;span class="kwrd"&gt;AND&lt;/span&gt; @&lt;span class="kwrd"&gt;index&lt;/span&gt; &amp;gt; @&lt;span class="kwrd"&gt;next&lt;/span&gt; &lt;br/&gt;            &lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;&lt;br/&gt;                &lt;span class="kwrd"&gt;SET&lt;/span&gt; @&lt;span class="kwrd"&gt;start&lt;/span&gt; = @location + @seed&lt;br/&gt;                &lt;span class="kwrd"&gt;SET&lt;/span&gt; @location = CHARINDEX(@split, @String, @&lt;span class="kwrd"&gt;start&lt;/span&gt;)&lt;br/&gt;                &lt;span class="kwrd"&gt;SET&lt;/span&gt; @&lt;span class="kwrd"&gt;next&lt;/span&gt; = @&lt;span class="kwrd"&gt;next&lt;/span&gt; + 1&lt;br/&gt;            &lt;span class="kwrd"&gt;END&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;IF&lt;/span&gt; @location = 0 &lt;br/&gt;            &lt;span class="kwrd"&gt;SELECT&lt;/span&gt;  @location = LEN(@String) + 1 &lt;br/&gt;  &lt;br/&gt;        &lt;span class="kwrd"&gt;RETURN&lt;/span&gt; &lt;span class="kwrd"&gt;SUBSTRING&lt;/span&gt;(@String,@&lt;span class="kwrd"&gt;start&lt;/span&gt;,@location-@&lt;span class="kwrd"&gt;start&lt;/span&gt;)&lt;br/&gt;    END&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;自SQL Server 2005起就开始集成CLR，允许.NET托管代码运行于SQL Server中，用我们熟悉的.NET API可以轻易的完成任务。打开Visual Stdio 2010，创建一个SQL Server CLR项目，SQL Server CLP函数的源代码清单如下&lt;/p&gt;[Microsoft.SqlServer.Server.SqlFunction]&lt;br/&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; SqlString Split(&lt;span class="kwrd"&gt;string&lt;/span&gt; UserLine,&lt;span class="kwrd"&gt;int&lt;/span&gt; Index)&lt;br/&gt;{&lt;br/&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(UserLine))&lt;br/&gt;        {&lt;br/&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt;[] lines = Regex.Split(UserLine, &lt;span class="str"&gt;" # "&lt;/span&gt;);&lt;br/&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (lines.Length == 3)&lt;br/&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; SqlString(lines[Index]);&lt;br/&gt;            &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br/&gt;                &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ApplicationException(&lt;span class="str"&gt;"invalid input line"&lt;/span&gt;);&lt;br/&gt;        }&lt;br/&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; SqlString(&lt;span class="str"&gt;""&lt;/span&gt;);&lt;br/&gt;}&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;它的调用方法和TSQL函数的方式一样，如下图所示&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/201112230908491875.png"&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;SELECT&amp;nbsp; dbo.Split(User,0) AS&amp;nbsp; [User Id]&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dbo.Split(User,1)&amp;nbsp; AS [Password]&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dbo.Split(User,2) AS [Email]&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM CsdnUser&lt;/p&gt;&lt;p&gt;顺利完成第一题，如果你有更好的方法，欢迎留言。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;对于密码是否用明文，是否要加密，各种情况下所采取的方法都有道理。不给密码加密，明文传送是不值得推荐，不过冒似很多系统都是用明文保存在数据库中的。如果你担心明文不好，容易被人家获取到，可以采用可逆的加密。请参考我的文章《数据加密小工具》，它对需要保护的数据进行简单的加密，也很容易的逆反到当初的明文&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/201112230908504973.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/JamesLi2015/201112/201112230908508909.png" width="784" height="264" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;在我的知识管理系统Data Solution的用户反馈功能中，用户输入反馈的内容，发送到指定的邮箱中，因为使用的是smtp的方式，所以要把用户名和密码写到程序中去，但为了防止别人很轻易的从IL代码中读到到我的邮件的帐号和密码，我就使用了上面的可逆加密的方法，把邮件帐号和密码进行加密后，再放到程序代码中，这样可以增加被破解的难度。也没有把很重要的资料放到这个用于接受用户反馈的邮件帐号中，毕竟还是可能被人家破解的。&lt;/p&gt;&lt;p&gt;再进一步的，可以采用.NET提供的算法，进行Hash运算或是加密。MD5是公认的不可逆的加密算法，它的调用方法如下&lt;/p&gt;&lt;span class="kwrd"&gt;byte&lt;/span&gt;[] Original = Encoding.Default.GetBytes(txt_Source.Text); &lt;br/&gt;MD5 s1 = MD5.Create(); &lt;span class="rem"&gt;//使用MD5 &lt;/span&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;byte&lt;/span&gt;[] Change = s1.ComputeHash(Original);  加密 &lt;br/&gt;txt_Result.Text = Convert.ToBase64String(Change);&lt;p&gt;请参考文章《&lt;a href="http://www.dotblogs.com.tw/jeff-yeh/archive/2008/06/25/4371.aspx"&gt;使用MD5將字串加密 C# VS2005 Sample Code&lt;/a&gt;》学习MD5的调用方法。&lt;/p&gt;&lt;p&gt;如果你需要MD5的调用例子代码，下面的代码应该可以帮助到你,代码来原于园子里的朋友， &lt;br /&gt;地址是&lt;a title="http://www.cnblogs.com/konooo/archive/2009/01/22/1379920.html" href="http://www.cnblogs.com/konooo/archive/2009/01/22/1379920.html"&gt;http://www.cnblogs.com/konooo/archive/2009/01/22/1379920.html&lt;/a&gt;&amp;nbsp;&lt;/p&gt; &lt;span class="rem"&gt;/// MD5 16位加密 加密后密码为大写&lt;/span&gt;&lt;br/&gt; &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span class="rem"&gt;/// &amp;lt;param name="ConvertString"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetMd5Str(&lt;span class="kwrd"&gt;string&lt;/span&gt; ConvertString)&lt;br/&gt;{&lt;br/&gt;      MD5CryptoServiceProvider md5 = &lt;span class="kwrd"&gt;new&lt;/span&gt; MD5CryptoServiceProvider();&lt;br/&gt;      &lt;span class="kwrd"&gt;string&lt;/span&gt; t2 = BitConverter.ToString(md5.ComputeHash(UTF8Encoding.Default.GetBytes(ConvertString)), 4, 8);&lt;br/&gt;      t2 = t2.Replace(&lt;span class="str"&gt;"-"&lt;/span&gt;, &lt;span class="str"&gt;""&lt;/span&gt;);&lt;br/&gt;      &lt;span class="kwrd"&gt;return&lt;/span&gt; t2;&lt;br/&gt;} &lt;br/&gt;&lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span class="rem"&gt;/// MD5 16位加密 加密后密码为小写&lt;/span&gt;&lt;br/&gt;&lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span class="rem"&gt;/// &amp;lt;param name="ConvertString"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetMd5Str(&lt;span class="kwrd"&gt;string&lt;/span&gt; ConvertString)&lt;br/&gt;{&lt;br/&gt;      MD5CryptoServiceProvider md5 = &lt;span class="kwrd"&gt;new&lt;/span&gt; MD5CryptoServiceProvider();&lt;br/&gt;      &lt;span class="kwrd"&gt;string&lt;/span&gt; t2 = BitConverter.ToString(md5.ComputeHash(UTF8Encoding.Default.GetBytes(ConvertString)), 4, 8);&lt;br/&gt;      t2 = t2.Replace(&lt;span class="str"&gt;"-"&lt;/span&gt;, &lt;span class="str"&gt;""&lt;/span&gt;);&lt;br/&gt;      t2 = t2.ToLower();&lt;br/&gt;      &lt;span class="kwrd"&gt;return&lt;/span&gt; t2;&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;&lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span class="rem"&gt;/// MD5　32位加密&lt;/span&gt;&lt;br/&gt;&lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span class="rem"&gt;/// &amp;lt;param name="str"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;static&lt;/span&gt;  &lt;span class="kwrd"&gt;string&lt;/span&gt; UserMd5(&lt;span class="kwrd"&gt;string&lt;/span&gt; str)&lt;br/&gt;{&lt;br/&gt;      &lt;span class="kwrd"&gt;string&lt;/span&gt; cl = str;&lt;br/&gt;      &lt;span class="kwrd"&gt;string&lt;/span&gt; pwd = &lt;span class="str"&gt;""&lt;/span&gt;;&lt;br/&gt;      MD5 md5 = MD5.Create();&lt;span class="rem"&gt;//实例化一个md5对像&lt;/span&gt;&lt;br/&gt;      &lt;span class="rem"&gt;// 加密后是一个字节类型的数组，这里要注意编码UTF8/Unicode等的选择　&lt;/span&gt;&lt;br/&gt;      &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(cl));&lt;br/&gt;      &lt;span class="rem"&gt;// 通过使用循环，将字节类型的数组转换为字符串，此字符串是常规字符格式化所得&lt;/span&gt;&lt;br/&gt;      &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; s.Length; i++)&lt;br/&gt;      {&lt;br/&gt;       &lt;span class="rem"&gt;// 将得到的字符串使用十六进制类型格式。格式后的字符是小写的字母，如果使用大写（X）则格式后的字符是大写字符 &lt;/span&gt;&lt;br/&gt;       pwd = pwd + s[i].ToString(&lt;span class="str"&gt;"X"&lt;/span&gt;);&lt;br/&gt;      }&lt;br/&gt;      &lt;span class="kwrd"&gt;return&lt;/span&gt; pwd;&lt;br/&gt;}&lt;p&gt;前几年是经常在CSDN上逛，也喜欢它的下载频道，可以找到很多资源，后来下载资源要积分的，没有分就不能下载，于是自己注册了多个CSDN的帐号，只用来下载资源。这里我有两句微词，既然是共享目的，为何要限制别人下载呢？新浪的爱问知识人就没有这么复杂的下载规则，即使被下载的文件需要积分，你也可以找到不要分的，免限制下载的资源。还有一条规则，如果你的CSDN帐号不够一定的级别，只能上传，但不能删除你上传的文件。我自己也曾在CSDN上发布过软件程序，后来有新版本发布，无法自己删除旧版本的程序，要到论坛去发贴子，依靠管理员才能删除，就这一条，使我彻底放弃了把CSDN作为程序代码的发布渠道。 不过，CSDN还是对我们的技术有过很大的帮助，遇到问题用Baidu搜索到的头条通常就是CSDN的论坛的贴子，这一点要对CSDN表示感谢和致敬。&lt;/p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;img src="http://www.cnblogs.com/JamesLi2015/aggbug/2298825.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/JamesLi2015/archive/2011/12/23/2298825.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
