<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:wfw="http://wellformedweb.org/CommentAPI/">
  <channel>
    <title><![CDATA[soho-works BLOG]]></title> 
    <link>http://www.soho-works/blog</link> 
    <description><![CDATA[ my toy]]></description> 
    <language>zh-cn</language> 
    <copyright><![CDATA[Copyright 2008]]></copyright> 
    <webMaster><![CDATA[jiangjianxiao@gmail.com]]></webMaster> 
    <generator>jjx</generator> 
    <pubDate><![CDATA[2012-02-14 20:48:32.991805]]></pubDate> 
    <ttl>60</ttl>
  
    <item>
      <title><![CDATA[delphi 强类型数据集]]></title> 
      <link><![CDATA[ ]]></link> 
      <category><![CDATA[Delphi]]></category> 
      <author><![CDATA[jiangjianxiao]]></author> 
      <pubDate>2008-06-25 02:39:30.385256</pubDate> 
      <description><![CDATA[
      <p>在delphi中，访问TDataSet的子类字段通常用FindByName，其实可以用类似ado.net 强类型数据集的方法来完成，简单的例子</p>
<p>unit Unit10;<br /><br />interface<br />uses ADODB,classes,DB,variants,dialogs;<br /><br />type<br />TPermission=class(TADODataSet)<br />&nbsp; constructor create(owner:TComponent);override;<br />&nbsp; public<br />&nbsp; security_key_id:TIntegerField;<br />&nbsp; id:TIntegerField;<br />&nbsp; group_id:TIntegerField;<br />&nbsp; access_level:TIntegerField;<br /><br /><br />end;<br /><br />procedure test;<br />implementation<br />constructor TPermission.create(owner: TComponent);<br />begin<br />&nbsp; inherited Create(owner);<br />&nbsp; //创建字段<br />&nbsp; self.CommandType:=cmdTable;<br />&nbsp; CommandText:='permissions';<br /><br /><br />&nbsp; security_key_id:=TIntegerField.Create(self);<br />&nbsp; security_key_id.FieldName:='security_key_id';<br />&nbsp; id:=TIntegerField.Create(self);<br />&nbsp; id.fieldName:='id' ;<br /><br />&nbsp; group_id:=TIntegerField.Create(self);<br />&nbsp; group_id.fieldName:='group_id';<br />&nbsp; access_level:=TIntegerField.create(self);<br />&nbsp; access_level.fieldName:='access_level';<br /><br /><br />//设置dataset，同时会将字段加入到fields集合<br />&nbsp; security_key_id.DataSet:=self;<br />&nbsp; id.DataSet:=self;<br />&nbsp; group_id.DataSet:=self;<br />&nbsp; access_level.dataset:=self;<br /><br /><br />end;<br /><br />procedure test;<br />var<br />&nbsp; p:TPermission;<br /><br />begin<br />&nbsp; p:=TPermission.Create(nil);<br />&nbsp; p.ConnectionString:='.................................................';<br />&nbsp; p.Active:=true;<br />&nbsp; while not p.eof do begin<br /><br />&nbsp;&nbsp;&nbsp; showmessage(vartostr(p.security_key_id.Value));<br />&nbsp;&nbsp;&nbsp; p.Next;<br />&nbsp; end;<br />end;<br />end.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>其实，如果delphi的index 属性支持字符串的话，可以定义出更高效的类，yy的</p>
<p>TPermission=class(TADODataSet)<br />&nbsp;published<br />&nbsp;property security_key_id:TField index 'security_key_id' read fieldByname;<br />&nbsp;property group_id:TField index 'group_id' read fieldbyname;<br />&nbsp;property id:TField:TField index 'id' read fieldbyname<br />&nbsp;property access_level:TField index 'id' read fieldbyname<br /><br /><br />end;</p>
<p>&nbsp;</p>
<p>&nbsp;</p> ]]></description>
    </item>

    <item>
      <title><![CDATA[paxscript]]></title> 
      <link><![CDATA[ ]]></link> 
      <category><![CDATA[Delphi]]></category> 
      <author><![CDATA[jiangjianxiao]]></author> 
      <pubDate>2008-06-18 14:41:44.531428</pubDate> 
      <description><![CDATA[
      <p>basic</p>
<p>一句话，还真不错，有很多vb.net的语法，但又有些不同，比方说 过程无需带(),写了一段调用adodb的脚本，跑起来速度不赖，同vbscript差不多。</p>
<p>接下去，测试了字符串连接，类似</p>
<p>s=s &amp; rs.fields("field").value &amp; "\r\n" &rsquo;后面这个\r\n应该不是vb的特征</p>
<p>&nbsp;</p>
<p>发现速度下来了，可见字符串处理效率不高，但想到其可以调用delphi 的vcl库，试着想使用vcl的字符串类，如TStringList，发现运行到add就卡壳</p>
<p>imports classes 'delphi classes 单元</p>
<p>dim s as TStringList</p>
<p>s=new TStringList</p>
<p>s.Add("test")</p>
<p>不支持的特色</p>
<p>1. is 操作符 typeof c is integer</p>
<p>2. 不能在定义时创建新对象，如dim c as new MyObject</p>
<p>&nbsp;</p>
<p>javascript</p>
<p>1. 注意单元引用，如 using a in './units/a.pp'</p>
<p>&nbsp;bug</p>
<p>var a = new Array(3)<br />a[2] = 12;<br />//println a;<br />//println a.length;<br />a[5] = 36;<br />//println a;<br />//println a.length;<br />var d = a.concat([1,2,3]);<br />println d.length;<br />println d;</p>
<p>这段脚本居然丢失 a[5].&nbsp; 结果为,,12,,,1,2,3 ，长度为8,显然,contact冲掉了最后一个元素</p>
<p>如果 写</p>
<p>a=[1,2,3];</p>
<p>a.conact([4,5,6]); //不认这个conact</p>
<p>看来是不能用了</p>
<p>&nbsp;</p>
<p>&nbsp;</p> ]]></description>
    </item>

    <item>
      <title><![CDATA[curl的许可]]></title> 
      <link><![CDATA[ ]]></link> 
      <category><![CDATA[RIA]]></category> 
      <author><![CDATA[jiangjianxiao]]></author> 
      <pubDate>2008-06-14 08:47:02.417322</pubDate> 
      <description><![CDATA[
      <p>被infoq 上的 curl 6.0 比actionscript 3.0快8倍的消息刺激了一下，所以这几天又留心了一下curl. 说到又，是这个东西很早前就关注过，不过被它的语法搞晕了。 不过现在再来看，倒也不难，无非是一种置标语言+代码，同 xml 内嵌代码没什么区别，比方说</p>
<p>{CommandButton label="test"}，你可以看成&lt;CommandButton label="test"/&gt;或是</p>
<p>CommandButton but=new CommandButton{label="test"}</p>
<p>当然这句更等效的是</p>
<p>{let but:CommandButton={CommandButton label="test"}}</p>
<p>n多的大括号:(</p>
<p>这东西的许可在这里，<a href="http://www.curl.com/products_licensing.php" target="_blank">http://www.curl.com/products_licensing.php</a>&nbsp;大致看了一下，这公司大有酒香不怕巷子深的意味。</p>
<p>首先，基本使用是免费的，不过对照 pro的许可，会发现一些功能缺失（而且对是针对企业级应用的，像https,encryption,concurrency,所以免费使用的许可也只能说是玩具）</p>
<li>Https support </li>
<li>Complex concurrency </li>
<li>Running with privilege </li>
<li>Encryption &amp; pCurl </li>
<li>Single sign-on </li>
<li>QTP integration </li>
<p>就算是免费的，在web上部署，你也需要申请许可，当然本地和localhost不需要</p>
<p>ide 的pro版本有60天的免费使用期，要收费的，不过你可以免费使用非pro版本</p>
<p>6.0是传统的ria应用，7.0 代号nitro ，选air ，加入了离线内容</p>
<p>对比一下,siliverlight ，走开放路线，基本可能达到免费,flex 也是走开放路线，基本可以达到免费的程度。而你这个样子，凭什么啊？</p> ]]></description>
    </item>

    <item>
      <title><![CDATA[我的第一篇在app engine上的blog]]></title> 
      <link><![CDATA[ ]]></link> 
      <category><![CDATA[App Engine]]></category> 
      <author><![CDATA[jiangjianxiao]]></author> 
      <pubDate>2008-06-13 10:48:12.744533</pubDate> 
      <description><![CDATA[
      <p>虽然粗糙，但都是自己一行一行 代码垒起来的，虽然代码也没有几行:), 我的数据是通过urllib post上来的，结果是没有作者字段。 app engine缺少一种通过email 获取user对象的方法。 为了将user字段补充完成。 我写了这样一个方法</p>
<p>@check_login<br />def update_author(request):<br />&nbsp;&nbsp;for blog in Blog.all():<br />&nbsp;&nbsp;blog.user=users.get_current_user()<br />&nbsp;&nbsp;blog.put()<br />&nbsp;return HttpResponse("Update author finish!")</p>
<p>结果如何，超时错误，然后换成这样</p>
<p>@check_login<br />def update_author(request):<br />&nbsp;user=users.get_current_user()<br />&nbsp;for blog in Blog.all():<br />&nbsp;&nbsp;blog.user=user<br />&nbsp;&nbsp;blog.put()<br />&nbsp;return HttpResponse("Update author finish!")</p>
<p>pass</p>
<p>&nbsp;</p>
<p>最近的blog都没有技术含量，呵呵 ，datastore没有一种批量更新的方法吗？ 我现在没有发现，类似 update Blog set user=:1，倒是删除有针对集合的操作&nbsp;&nbsp;,另外，像这样的场合，使用事务处理应该会快些吧</p>
<p>这东西一开始用app engine自身的RequestHandler机制写的，我写了一个简单的mvc类来简化开发，记录在这里，备忘吧</p>
<p>main.py</p>
<p>&nbsp;application=webapp.WSGIApplication(<br />&nbsp;&nbsp;[&nbsp;&nbsp; ('/(?P&lt;app&gt;\w+?)/(?P&lt;controller&gt;\w+?)(?:/(?P&lt;action&gt;\w+?))?(?:/(?P&lt;id&gt;\d+?))?(?:\?\w*)?',contrib.mvc.DispatchRequestHandler)</p>
<p>&nbsp;</p>
<p>class DispatchRequestHandler(webapp.RequestHandler):<br />&nbsp;&nbsp;&nbsp; def __init__(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(DispatchRequestHandler,self).__init__()<br />&nbsp;&nbsp;&nbsp; def dispatch(self,app,controller,action=None,id=None):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; module="%s.%s_controller" %(app.lower(),controller.lower())<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m = __import__(module)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for i in module.split(".")[1:]:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m = getattr(m, i)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; path=os.path.dirname(m.__file__)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Controller=getattr(m,"%sController" % controller.capitalize())<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c=Controller(self,path)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if action is None:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; action='index'<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; func=getattr(c,action)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if id is None:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; func()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; func(id)<br />&nbsp;&nbsp;&nbsp; def get(self,app,controller,action=None,id=None):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.dispatch(app,controller,action,id)<br />&nbsp;&nbsp;&nbsp; def post(self,app,controller,action=None,id=None):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.dispatch(app,controller,action,id)</p>
<p>Controller基类</p>
<p>class Controller(object):<br />&nbsp;&nbsp;&nbsp; def __init__(self,handler,path):</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.handler=handler<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.request=handler.request<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.response=handler.response<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.path=path<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.flush=Flush()<br />&nbsp;&nbsp;&nbsp; @property<br />&nbsp;&nbsp;&nbsp; def method(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return self.request.method<br />&nbsp;&nbsp;&nbsp; def redirect(self,uri,t=False):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.handler.redirect(uri,t)</p>
<p>&nbsp; <br />&nbsp;&nbsp;&nbsp; def error(self,code):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.response.set_status(code)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.response.clear()</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; def render_to_response(self,file,values=None):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; path=os.path.join(self.path,"templates",file)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.response.out.write(template.render(path,values))<br />&nbsp;&nbsp;&nbsp; #new，GET请求，返回一个用于创建资源的表单<br />&nbsp;&nbsp;&nbsp; def new(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pass<br />&nbsp;&nbsp;&nbsp; #show，处理针对单个资源的GET请求<br />&nbsp;&nbsp;&nbsp; def show(self,id):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pass<br />&nbsp;&nbsp;&nbsp; #create，处理POST请求，并将创建一个新资源<br />&nbsp;&nbsp;&nbsp; def create(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pass<br />&nbsp;&nbsp;&nbsp; #edit，GET请求，返回一个用于更新资源的表单<br />&nbsp;&nbsp;&nbsp; def edit(self,id):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pass<br />&nbsp;&nbsp;&nbsp; #update，处理PUT请求，并更新指定的资源<br />&nbsp;&nbsp;&nbsp; def index(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pass<br />&nbsp;&nbsp;&nbsp; #update，处理PUT请求，并更新指定的资源<br />&nbsp;&nbsp;&nbsp; def update(self,id):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pass<br />&nbsp;&nbsp;&nbsp; #destroy，处理DELETE请求，销毁一个资源<br />&nbsp;&nbsp;&nbsp; def destroy(self,id):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pass</p>
<p>&nbsp;</p>
<p>&nbsp;</p> ]]></description>
    </item>

    <item>
      <title><![CDATA[django小提示-FormPreview中的BooleanField]]></title> 
      <link><![CDATA[ ]]></link> 
      <category><![CDATA[Python]]></category> 
      <author><![CDATA[jiangjianxiao]]></author> 
      <pubDate>2007-12-06 11:59:12</pubDate> 
      <description><![CDATA[
      <p>这个问题得确是django的 bug <br />问题在于django 总是将BooleanField的值处理成True,False,但有个地方存在不一致的地方,就是 <br />CheckboxInput的value_form_datadict方法</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter"><ol class="dp-j">
<li class="alt"><span><span>def&nbsp;value_from_datadict(self,&nbsp;data,&nbsp;files,&nbsp;name):&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;name&nbsp;not&nbsp;in&nbsp;data:&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;A&nbsp;missing&nbsp;value&nbsp;means&nbsp;False&nbsp;because&nbsp;HTML&nbsp;form&nbsp;submission&nbsp;does&nbsp;not&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;send&nbsp;results&nbsp;<span class="keyword">for</span><span>&nbsp;unselected&nbsp;checkboxes.&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;False&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;</span><span class="keyword">super</span><span>(CheckboxInput,&nbsp;self).value_from_datadict(data,&nbsp;files,&nbsp;name)&nbsp;&nbsp;</span></span></li>
</ol></div>
</div>
<p><br />这个方法会导致一些错误,因为 data是个字符串的词典,因此,这个方法会返回bool的False(当data中没有is_test时)或字符串的'False'(当存在,但值为False时) <br />第一个是hash 值的计算,一开始的bool类型的False同unicode字符串的False是不同 的. 这样会导致当不核选时需要提交两次 <br />其次是当render的时候,可以查看CheckboxInput的render方法,里面有个check_test,默认被设置为bool,这样,当调用bool('False')时,返回的就是True了</p>
<p>所以,修改上面的方法(或继承新建一个Checkbox2Input),让其根据实际情况返回bool值就ok了 <br />比方说(这只是个quick and dirty的解决方法,英语好的可以提交bug,让django团队来处理这个问题)</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter"><ol class="dp-j">
<li class="alt"><span><span>def&nbsp;value_from_datadict(self,&nbsp;data,&nbsp;files,&nbsp;name):&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;name&nbsp;not&nbsp;in&nbsp;data:&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;A&nbsp;missing&nbsp;value&nbsp;means&nbsp;False&nbsp;because&nbsp;HTML&nbsp;form&nbsp;submission&nbsp;does&nbsp;not&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;send&nbsp;results&nbsp;<span class="keyword">for</span><span>&nbsp;unselected&nbsp;checkboxes.&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;False&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#print&nbsp;data[name],<span class="string">"value_form_datadict"</span><span>,type(data[name])&nbsp;&nbsp;</span></span></li>
<li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result=<span class="keyword">super</span><span>(CheckboxInput,&nbsp;self).value_from_datadict(data,&nbsp;files,&nbsp;name)&nbsp;&nbsp;</span></span></li>
<li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;True&nbsp;</span><span class="keyword">if</span><span>&nbsp;result&nbsp;in&nbsp;['on','ON','True','</span><span class="keyword">true</span><span>']&nbsp;</span><span class="keyword">else</span><span>&nbsp;False&nbsp;&nbsp;</span></span></li>
</ol></div>
</div>
<p>由于存在这两个问题,因此光传入一个check_test lambda 还不足以解决问题,我一开始就以为这个能解决,呵呵</p> ]]></description>
    </item>

    <item>
      <title><![CDATA[django小提示-maxlength,max_length]]></title> 
      <link><![CDATA[ ]]></link> 
      <category><![CDATA[Python]]></category> 
      <author><![CDATA[jiangjianxiao]]></author> 
      <pubDate>2007-11-30 15:17:07</pubDate> 
      <description><![CDATA[
      <p>在django 0.96,CharField的的最大长度使用maxlength<br />在svn的代码中,这个已经修改为max_length(这样,更符合python一般的命名规范,当然,事实上python并没有像ruby一样对命名规范有严格的要求,比方说unittest,wxpython就使用两个不同的命名规范),但实际上,原先的代码并不会出错,django是如何达成的呢<br /><br />这里,django 使用了metaclass的功能<br /><br />1. 首先,查看Field对象的定义,你会发现<br />class Field(object):<br />&nbsp;&nbsp;&nbsp; __metaclass__ = LegacyMaxlength<br /><br />LegacyMaxLength定义在django.utils.maxlength 模块中,这个metaclass非常简单<br />class LegacyMaxlength(type):<br />&nbsp;&nbsp;&nbsp; def __init__(cls, name, bases, attrs):<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(LegacyMaxlength, cls).__init__(name, bases, attrs)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #对构造函数进行修饰<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cls.__init__ = remove_maxlength(cls.__init__)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #增加maxlength属性&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cls.maxlength = property(get_maxlength, set_maxlength)<br /><br />remove_maxlength巧妙的运用了decorate ,对class 构造进行进行处理,流程很简单,就是从参数中取max_length,maxlength,如果有maxlength,则给你个已过期的警告,如果你同时设置了max_length和maxlength,则给你来个错误(因为 django这样无法判断你用 那个),然后将maxlenth设置给max_length,并创建maxlength属性<br /><br />这样Field class的代码本身就非常干净,并没有为保持兼容性而同时存在maxlength和max_length两个属性. (虽然实际生成的代码还是有两个的,一个是max_length field还有一个是通过metaclass生成的maxlength property)<br /><br />这里django 巧妙的利用metaclass实现deprecated 功能的.<br /><br />在django的代码中,对于类似dsl的功能,django主要利用metaclass和descriptor来达成的,比方说model ,django构造了一个ModelBase metaclass,然后让Model使用这个元类,像对于关系处理, ForeignKey最终是将使用ReverseSingleRelatedObjectDescriptor 这样的 descriptor对象,也就是说,当你遇到<br />class Customer(models.Model):<br />&nbsp;&nbsp; &nbsp;shipping_address=models.ForeignKey(Address)<br /><br />最后,这个类被解释执行后的shipping_address实际上是一个叫shipping_address的ReverseSingleRelatedObjectDescriptor 的实例. <br /><br />descriptor和metaclass的基本知识,我推荐参阅这这几个链接<br />How-To Guide for Descriptors<br />http://users.rcn.com/python/download/Descriptor.htm#static-methods-and-class-methods<br />我强烈推荐这个文档, 看后你会知道descriptor 包括property,staticmethod,classmethod到底是如何运作的,也会理解bound(bind)在动态语言中的作用.<br />Python 中的元类编程 -将面向对象编程推向新的高度<br />http://www.ibm.com/developerworks/cn/linux/l-pymeta/index.html<br />Python 中的元类编程，第 2 部分- 理解继承的奥秘和实例创建<br />http://www.ibm.com/developerworks/cn/linux/l-pymeta2/index.html<br /></p> ]]></description>
    </item>

    <item>
      <title><![CDATA[django小提示-json]]></title> 
      <link><![CDATA[ ]]></link> 
      <category><![CDATA[Python]]></category> 
      <author><![CDATA[jiangjianxiao]]></author> 
      <pubDate>2007-11-28 16:37:21</pubDate> 
      <description><![CDATA[
      <p>django提供了基于json,yaml,xml的串行化支持. 这里我们主要来讲json<br />django对json 的支持有两个层次<br />第一个层次在django.utils.simplejson包中 ,JSONEncoder 提供了常见python数据类型像tuple,list,dict,string,float,decimal等的支持,但这里,并不包含对自定义python对象的json支持<br />第二个层次在django.core.serializers 包中,这个包提供了对json,yaml(如果你安装了pyyaml的话,xml的串行化支持. 注意,在这里,只能串行化querySet,而且,你只能在django项目内部使用(当然你可以通过手动将项目路径加入到sys.path并设置&nbsp;&nbsp;&nbsp; os.environ["DJANGO_SETTINGS_MODULE"] = myproject.settings' 来在非django项目中使用)<br /><br /><br />第一个层次可以在其他非django 项目中使用,你需要继承JSONEncoder,并覆盖default方法,比方说你有一个Employee对象<br /><br />class Employee:<br />&nbsp;&nbsp;&nbsp; def __init__(self,name):<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; self.name=name<br /><br />from django.utils.simplejson.encoder import JSONEncoder<br />class ObjectJSONEncoder(JSONEncoder):<br />&nbsp;&nbsp;&nbsp; def default(self,o):<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if hasattr(o,"__dict__")<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; return o.__dict__<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return super(ObjectJSONEncoder,self).default(o)<br /><br /># test<br /><br />data=[1,{'a':'a'},Employee('jjx')]<br />import django.utils.simplejson<br /><br />print django.utils.simplejson.dumps(data,cls=ObjectJSONEncoder)<br /><br /><br />[1, {"a": "a"}, {"name": "jjx"}]<br /><br /><br />当使用第二个层次时,你可以通过传递fields 参数选择输出的字段,也可以传入一个io对象<br /><br />from django.core.serializers import seralize<br />from cStringIO import StringIO<br />stream=StringIO()<br /><br />seralize('json',User.objects.all(),stream=stream,fields=['username'])<br />print stream.getvalue()<br /><br />当将json输出到浏览器时,你可以传递mimetype参数为text/json或text/javascript<br />return HttpResponse(json_str,mimetype="text/json")<br /><br /><strong>update </strong>django snippets 上有 个JsonResponse类, 可以参考<br />http://www.djangosnippets.org/snippets/154/</p>
<pre><span class="k">from</span> <span class="nn">django.core.serializers</span> <span class="k">import</span> <span class="n">serialize</span><br /><span class="k">from</span> <span class="nn">django.db.models.query</span> <span class="k">import</span> <span class="n">QuerySet</span><br /><span class="k">from</span> <span class="nn">django.http</span> <span class="k">import</span> <span class="n">HttpResponse</span><br /><span class="k">from</span> <span class="nn">django.utils</span> <span class="k">import</span> <span class="n">simplejson</span><br /><br /><span class="k">class</span> <span class="nc">JsonResponse</span><span class="p">(</span><span class="n">HttpResponse</span><span class="p">):</span><br />    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">object</span><span class="p">):</span><br />        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="nb">object</span><span class="p">,</span> <span class="n">QuerySet</span><span class="p">):</span><br />            <span class="n">content</span> <span class="o">=</span> <span class="n">serialize</span><span class="p">(</span><span class="s">'json'</span><span class="p">,</span> <span class="nb">object</span><span class="p">)</span><br />        <span class="k">else</span><span class="p">:</span><br />            <span class="n">content</span> <span class="o">=</span> <span class="n">simplejson</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="nb">object</span><span class="p">)</span><br />        <span class="nb">super</span><span class="p">(</span><span class="n">JsonResponse</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="n">content</span><span class="p">,</span> <span class="n">mimetype</span><span class="o">=</span><span class="s">'application/json'</span><span class="p">)</span> </pre> ]]></description>
    </item>

    <item>
      <title><![CDATA[django小提示-打印sql语句]]></title> 
      <link><![CDATA[ ]]></link> 
      <category><![CDATA[Python]]></category> 
      <author><![CDATA[jiangjianxiao]]></author> 
      <pubDate>2007-11-28 11:05:03</pubDate> 
      <description><![CDATA[
      <p>当settings.Debug=True时,django 使用的是django.db.backets.util.CursorDebugWrapper ,这样,当你执行execute,executemany时,django会把你执行的语句加入到BaseDatabaseWrapper派生对象的queries列表,每次加入的是一个dict,包括sql和time<br />这样,你可以在任何时候打印connection对象的queries属性或是直接在CursorDebugWrapper的execute和executemany中加入print语句<br />如<br />def execute(....):<br />&nbsp;&nbsp;&nbsp; ...<br />&nbsp;&nbsp;&nbsp; print smart_unicode(sql) % convert_args(params),"%.3f" % (stop - start)<br /><br />在django中connection对象实际上就是BaseDatabaseWrapper的派生类<br />看这行<br />connection = backend.DatabaseWrapper(**settings.DATABASE_OPTIONS)<br /><br />再看backend模块是怎么来的<br />&nbsp;&nbsp;&nbsp; _import_path = 'django.db.backends.'<br />&nbsp;&nbsp;&nbsp; backend = __import__('%s%s.base' % (_import_path, settings.DATABASE_ENGINE), {}, {}, [''])<br /><br />显然,如果你的DATABASE_ENGINE为mysql的话,这个导入语句就是<br />__import("django.db.backends.mysql.base",{},{},[''])<br /><br />通常,mysqldb的cursor执行结果为一个tuple ,虽然这样效率较高,但有时 也不方便,你可以让 在创建真实的mysqldb connection对象时传入cursorclass参数<br /><br />修改django.db.backends.mysql.base.DatabaseWrapper<br />def _cursor(...):<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; #keargs['cursorclass']=Database.DictCursor # 加上这行<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.connection = Database.connect(**kwargs)<br /><br />或者在settings.py中增加<br />import MySQLdb<br />CURSOR_CLASS=MySQLdb.Cusor # 或者CURSOR_CLASS=MySQLdb.DictCursor<br /><br />然后<br />def _cursor(...):<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; keargs['cursorclass']=settings.CURSOR_CLASS # 加上这行<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.connection = Database.connect(**kwargs)<br /><br />你也可以修改<br />&nbsp; cursor = self.connection.cursor() 为 <br />&nbsp; cursor = self.connection.cursor(settings.CURSOR_CLASS)<br />效果是一样的</p> ]]></description>
    </item>

    <item>
      <title><![CDATA[asp.net mvc笔记- 替换自己的view engine,依赖注入]]></title> 
      <link><![CDATA[ ]]></link> 
      <category><![CDATA[Microsoft.NET]]></category> 
      <author><![CDATA[jiangjianxiao]]></author> 
      <pubDate>2007-11-26 18:03:58</pubDate> 
      <description><![CDATA[
      <h1><span class="Title">使用自己的view引擎</span></h1>
<p><br />asp.net mvc 的view引擎提供对asp.net page,usercontrol 的的支持. 你还可以创建自己的view引擎,过程非常简单1. 实现IView接口,比方说<br />public class NVelocityView : IView<br />{<br />&nbsp;&nbsp;&nbsp; public string ViewName<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; public string MasterName<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; public object ViewData<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; public void RenderView(ViewContext viewContext)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //用nvelocity解析模板,这个任务留给大家完成<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string context = string.Empty;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context = "解析后的内容";<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; viewContext.HttpContext.Response.Write(context);<br /><br />&nbsp;&nbsp;&nbsp; }<br /><br />}<br /><br />2. 实现IViewFactory接口<br />public class NVelocityViewFactory : IViewFactory<br />{<br />&nbsp;&nbsp;&nbsp; <br /><br />&nbsp;&nbsp;&nbsp; public IView CreateView(ControllerContext controllerContext, string viewName, string masterName, object viewData)<br />&nbsp;&nbsp;&nbsp; {<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp; new NVelocityView { ViewName = viewName ,MasterName=masterName,ViewData=viewData};<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; }<br /><br />&nbsp; <br />}<br />3. 继承Controller类,在类构造中设置ViewFactory参数<br />public class HomeController : Controller<br />{<br />&nbsp;&nbsp;&nbsp; public HomeController()<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ViewFactory = new NVelocityViewFactory();<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; [ControllerAction]<br />&nbsp;&nbsp;&nbsp; public void Index()<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp; }<br />}</p>
<h1><span class="Title">依赖注入</span></h1>
<p>4. 实现 IControllerFactory<br />在这里进行依赖注入,比方说调用<br />public class SpringControlFactory : IControllerFactory<br />{<br /><br />&nbsp; <br />&nbsp;&nbsp;&nbsp; public IController CreateController(RequestContext context, System.Type controllerType)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string requiredString = (string)context.RouteData.Values["controller"];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (IController)ContextRegistry.GetContext()[requiredString];<br /><br />&nbsp;&nbsp;&nbsp; }<br /><br />}<br />5. 设置controlerfactory<br />代码放到global.asax 的Application_Start中<br />&nbsp;<br />ControllerBuilder.Current.SetDefaultControllerFactory( typeof(SpringControlFactory));<br /><strong>更新 </strong>ControllerBuilder提供了SetControllerFactory和SetDefaultControllerFactory两个方法, 通常,SetControllerFactory是针对特定的controller类型的, 在这个场景,你想对所有的controller子类生效,就用 SetDefaultControllerFactory<br /><br />通过依赖注入,我们可以在外部实现修改ViewFactory的功能<br />&lt;object id="myViewFactory" type="xxx.NVelocityViewFactory,xxx"/&gt;<br />&lt;object id='Home' type="xxx.HomeController,xxx" singleton="false"&gt;<br />&lt;property name="ViewFactory" ref="myViewFactory"/&gt;<br />&lt;/object&gt;<br /><br />IControllerFactory 非常重要, 这里,你可以使用dlr ,整合ironpython和ironruby,因为你已经得到controller名,接下来你可以从文件系统中读取对应的ironpython或ironruby 文件,编译和执行它,返回给asp.net mvc<br />这个链接 描述了如何host ironruby 2.0 r6<br />http://blogs.msdn.com/rdawson/archive/2007/11/29/hosting-ironpython-2-0-alpha-6-via-the-dlr.aspx<br />而codeplex 上有个nwsgi 项目, 你可以参考如何使用ironpython来达成在asp.net实现一个wsgi实现的<br /><br /><br /><strong>大家可以看到,继承自己的view引擎和ioc功能和整合动态语言是非常简单的, asp.net mvc 只是提供了一个简单的层次.对于类似castle 项目,两者更多的是互补而不是竞争.比方说castle的route功能不强 ,orm 不足,更多的是缺少社区的关注.&nbsp; 利用asp.net mvc ,castle 可以更多的将眼光关注到具体的领域问题上.<br /><br /><br /></strong></p> ]]></description>
    </item>

    <item>
      <title><![CDATA[nwsgi]]></title> 
      <link><![CDATA[ ]]></link> 
      <category><![CDATA[]]></category> 
      <author><![CDATA[jiangjianxiao]]></author> 
      <pubDate>2007-11-14 15:21:19</pubDate> 
      <description><![CDATA[
      nwsgi是一个asp.net 上的wsgi实现(使用asp.net ihttphandler), 这样,理论上,你可以在asp.net 使用那些wsgi兼容的python web framework . 当然,最终能不能用,还是要看ironpython .一般来说,没有和c扩展交互的python应用,大部分可以顺利运行. 作者的例子中也用了paste/cherrypy. 不过至于django/pylons 之类的,就别想了.<br /><br />这项目还没有release,你可以从sourcecode中下载.如果打算用ironpython 做自己的web框架,使用nwsgi+paste或许是个不错的起点<br /><br />下载地址<br />http://www.codeplex.com/NWSGI ]]></description>
    </item>

    <item>
      <title><![CDATA[OnTableNewRow 的怪异举止]]></title> 
      <link><![CDATA[ ]]></link> 
      <category><![CDATA[Microsoft.NET]]></category> 
      <author><![CDATA[jiangjianxiao]]></author> 
      <pubDate>2007-11-11 10:43:01</pubDate> 
      <description><![CDATA[
      <p>显然,同一般的.net OnXX行为不同 ,通常的OnXX 会检查XX事件是否有设置,有的话就执行.<br /><br />这段代码在DataTable.NewRow 中被调用</p>
<table style="margin-bottom: 0px;" border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td style="padding: 4px 5px;" colspan="2" valign="top">
<pre><span style="color: #1000a0;">private</span> <a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Void" target="_blank" title="System.Void">void</a> <strong><a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Data:2.0.0.0:b77a5c561934e089/System.Data.DataTable/NewRowCreated(System.Data.DataRow)" target="_blank">NewRowCreated</a></strong>(<a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Data:2.0.0.0:b77a5c561934e089/System.Data.DataRow" target="_blank" title="System.Data.DataRow">DataRow</a> row)<br />{<br />    <span style="color: #1000a0;">if</span> (<span style="color: #1000a0;">this</span>.<a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Data:2.0.0.0:b77a5c561934e089/System.Data.DataTable/onTableNewRowDelegate:System.Data.DataTableNewRowEventHandler" target="_blank" title="DataTableNewRowEventHandler System.Data.DataTable.onTableNewRowDelegate;">onTableNewRowDelegate</a> != <span style="color: #800000;">null</span>)<br />    {<br />        <a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Data:2.0.0.0:b77a5c561934e089/System.Data.DataTableNewRowEventArgs" target="_blank" title="System.Data.DataTableNewRowEventArgs">DataTableNewRowEventArgs</a> <strong>e</strong> = <span style="color: #1000a0;">new</span> <a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Data:2.0.0.0:b77a5c561934e089/System.Data.DataTableNewRowEventArgs/.ctor(System.Data.DataRow)" target="_blank" title="System.Data.DataTableNewRowEventArgs.DataTableNewRowEventArgs(DataRow dataRow);">DataTableNewRowEventArgs</a>(<a target="_blank" title="DataRow row; // Parameter">row</a>);<br />        <span style="color: #1000a0;">this</span>.<a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Data:2.0.0.0:b77a5c561934e089/System.Data.DataTable/OnTableNewRow(System.Data.DataTableNewRowEventArgs)" target="_blank" title="void System.Data.DataTable.OnTableNewRow(DataTableNewRowEventArgs e);">OnTableNewRow</a>(<a target="_blank" title="DataTableNewRowEventArgs e // Local Variable">e</a>);<br />    }<br />}<br /></pre>
</td>
</tr>
</tbody>
</table>
<table style="margin-bottom: 0px;" border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td style="padding: 4px 5px;" colspan="2" valign="top">
<pre><span style="color: #1000a0;">protected</span> <span style="color: #1000a0;">virtual</span> <a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Void" target="_blank" title="System.Void">void</a> <strong><a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Data:2.0.0.0:b77a5c561934e089/System.Data.DataTable/OnTableNewRow(System.Data.DataTableNewRowEventArgs)" target="_blank">OnTableNewRow</a></strong>(<a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Data:2.0.0.0:b77a5c561934e089/System.Data.DataTableNewRowEventArgs" target="_blank" title="System.Data.DataTableNewRowEventArgs">DataTableNewRowEventArgs</a> e)<br />{<br />    <span style="color: #1000a0;">if</span> (<span style="color: #1000a0;">this</span>.<a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Data:2.0.0.0:b77a5c561934e089/System.Data.DataTable/onTableNewRowDelegate:System.Data.DataTableNewRowEventHandler" target="_blank" title="DataTableNewRowEventHandler System.Data.DataTable.onTableNewRowDelegate;">onTableNewRowDelegate</a> != <span style="color: #800000;">null</span>)<br />    {<br />        <a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Data:2.0.0.0:b77a5c561934e089/Bid" target="_blank" title="Bid">Bid</a>.<a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Data:2.0.0.0:b77a5c561934e089/Bid/Trace(String,Int32)" target="_blank" title="void Bid.Trace(string fmtPrintfW, int a1);">Trace</a>(<span style="color: #800000;">"&lt;ds.DataTable.OnTableNewRow|INFO&gt; %d#\n"</span>, <span style="color: #1000a0;">this</span>.<a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Data:2.0.0.0:b77a5c561934e089/System.Data.DataTable/property:ObjectID:Int32" target="_blank" title="int System.Data.DataTable.ObjectID { ... }">ObjectID</a>);<br />        <span style="color: #1000a0;">this</span>.<a href="http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://System.Data:2.0.0.0:b77a5c561934e089/System.Data.DataTable/onTableNewRowDelegate:System.Data.DataTableNewRowEventHandler" target="_blank" title="DataTableNewRowEventHandler System.Data.DataTable.onTableNewRowDelegate;">onTableNewRowDelegate</a>(<span style="color: #1000a0;">this</span>, <a target="_blank" title="DataTableNewRowEventArgs e; // Parameter">e</a>);<br />    }<br />}<br /></pre>
</td>
</tr>
</tbody>
</table>
<p><br />大家可以看到,NewRowCreated中在检查onTableNewRowDelegate了,如果这个没有设置,则OnTableNewRow是不会被触发的,因此, 比方说你想要一个自定义的事件,比方说 NewEntity ,你无法在OnTableNewRow来挂接它. 你要先挂接TableNewRow事件,然后这个OnTableNewRow才能生效.这不是开玩笑吗?<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //protected override void OnTableNewRow(DataTableNewRowEventArgs e)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp; base.OnTableNewRow(e);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp; if (this.NewEntity != null)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.NewEntity(this, new NewEntityEventArgs&lt;T&gt;((T)e.Row));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //}</p> ]]></description>
    </item>

    <item>
      <title><![CDATA[.net 3.5有多少特性可在windows 2000中使用]]></title> 
      <link><![CDATA[ ]]></link> 
      <category><![CDATA[]]></category> 
      <author><![CDATA[jiangjianxiao]]></author> 
      <pubDate>2007-11-07 17:46:05</pubDate> 
      <description><![CDATA[
      这个题目不好起,因为有些东西是编译器的,有些东西是库的 .(而有些是两者结合的,比方说ExtensionAttribute就在system.core.dll中)&nbsp; .net framework 3.0/3.5安装环境要求windows xp,但是现在企业中用windows 2000的也不少(大部分企业都需要好几年才会更新设备). 要放弃对windows 2000的支持,暂时还不太可能.<br />当target framework 设置为2.0 时,下面这些特性是支持的<br /><br /><strong>数组初始化支持</strong><br /><br />string[] s={'test','test'}<br /><br /><strong>集合初始化支持</strong><br />&nbsp;&nbsp;&nbsp; IList&lt;string&gt; s = new List&lt;string&gt; { &quot;name&quot;, &quot;name&quot; };<br /><br /><strong>类初始化支持<br />new Label{Text=&quot;label&quot;);<br /></strong><br /><strong>lambda 支持</strong><br />&nbsp;&nbsp;&nbsp; string[] list = new string[] { &quot;abc&quot;, &quot;12&quot;, &quot;java&quot; };<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string[] ll = Array.FindAll(list, s =&gt; (s.IndexOf(&quot;a&quot;) &gt;= 0));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach (string var in ll)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(var);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.ReadLine();<br /><br /><br /><strong>匿名类型支持</strong><br /><br />var emp=new {Name=&quot;jjx&quot;};<br /><br />把target framework设置为3.5 ,引用system.core.dll ,分发时带上system.core.dll ,这样 <strong>扩展方法也是支持的(经测试)<br /><br />带上system.linq.dll ,那么linq 表达式也是支持的,如</strong><strong><br /></strong>IList&lt;string&gt; names=new List&lt;string&gt;{&quot;test&quot;,&quot;test2&quot;};<br />var q=from n in names where n==&quot;test&quot; select n;<br /><br /><strong>更新<br />linq to sql&nbsp; 支持<br /></strong>.net framework 2.0 sp1 已经出来了,http://bbs.dotnettools.org/newsdetail.asp?id=5907 ,linq to sql 可以运行在windows 2000上<strong><br /></strong><strong><br /></strong> ]]></description>
    </item>

    <item>
      <title><![CDATA[jruby 1.1b1]]></title> 
      <link><![CDATA[ ]]></link> 
      <category><![CDATA[]]></category> 
      <author><![CDATA[jiangjianxiao]]></author> 
      <pubDate>2007-11-03 11:46:15</pubDate> 
      <description><![CDATA[
      jruby 昨天放出了1.1 b1 版本，1.1 版本的目录是能完整编译为aot(ahead of time)或jit（just in time)模式。更快，以及更小的内存占用，最大的同ruby 1.8兼容。<br /><br />下载 http://dist.codehaus.org/jruby/<br /><br />ironruby 的更新频率就明显的不如jruby了，不过好在过一段时间，就会有一次比较大的更新。这估计是开发模式的不同 .不过ironruby 的未来还是不明朗（比方说是不是把运行rails作为目标）。从 asp.net mvc将发布而言，这个估计是不可能了的。<br /><br />从这个链接可以更清楚的看到的asp.net mvc 应用的代码，http://www.sergiopereira.com/articles/aspnetmvc.html 。不过我不太喜欢这个示例，因为引入AccountViewData ,让人感觉还是在使用transaction script，而不是rails/django那种domain model driven 的方式。<br /><br />另外,关于 osx leopard 的发布, 我现在正在使用 macbook,经过一段时间到熟悉 ,osx 得确不错, 不过仔细想来,总是不是个滋味 .首先是 osx 实际 上是一个 拿unix 重新 包装了一下,就开发 付出而言,同ms的自行开发根本 难以 等同而语的. 而,osx却借助于unix的基础获得了稳定/安全的美名. 另外,就是ms的东西,一上来就非得装个杀毒软件,日子久了,运行速度越来越慢,也的确是个大问题.对于vista,我连甚至连尝试兴趣都没有. 也算是ms的一大失败吧.<br /><br />当然,现在,无论是osx/linux/unix都是无法取代windows的,但我想,市场 正在被这些操作系统所蚕食. ms应该需要意识这个问题了.<br /> ]]></description>
    </item>

    <item>
      <title><![CDATA[django小提示-send_mail]]></title> 
      <link><![CDATA[ ]]></link> 
      <category><![CDATA[]]></category> 
      <author><![CDATA[jiangjianxiao]]></author> 
      <pubDate>2007-10-31 15:32:59</pubDate> 
      <description><![CDATA[
      <p>django.core.mail.send_mail<br />这个函数在文档中被注明为deprecated。 但它还是可以一用的</p><p>首先，在settings.py中增加如下变量<br />EMAIL_HOST=&quot;&quot; #你的smtp 服务器ip 地址或名称<br />EMAIL_PORT=None # 不处理就用Noe，否则指明port<br />EMAIL_HOST_USER=&quot;你的用户名&quot; # 现在大部分邮箱都要求你输入 邮箱的全名<br />EMAIL_HOST_PASSWORD=&quot;&quot; # 你的口令<br />EMAIL_USE_TLS=None # 不处理就用None</p><p>然后就很简单的调用<br />from django.core.mail import send_mail<br /># help(send_mail)<br />send_mail ('subject','message','webmaster@easynew.com.cn',['jjx@easynew.com.cn'])</p><p>&nbsp;</p><p>这个函数为什么会被deprecated ，其实就是有点magic ，屏蔽了上面这些设置，所以，要明白点，就要用<br />connection = SMTPConnection(host,port,username,password,use_tls,fail_silently)<br />EmailMessage(subject, message, from_email, recipient_list, connection=connection).send()</p><p>其实是一样的，自己最后也会搞这样的函数，还不如直接用省事</p><p>注:<br /><strong>tls</strong> - Transport Layer Security 传输层安全<br />某些老旧的邮件服务器不认得TLS 协议，因此当你尝试加密连接时，握手会话失败 </p><p><strong>fail_silently</strong> 失败时就跳过，可查看SmtpConnection的_send函数<br />try:<br />&nbsp;&nbsp;&nbsp; #send mail<br />except:<br />&nbsp;&nbsp;&nbsp; if not self.fail_silentily:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raise<br />&nbsp;&nbsp;&nbsp; return false<br />return true&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br /></p> ]]></description>
    </item>

    <item>
      <title><![CDATA[djang小提示-login_required]]></title> 
      <link><![CDATA[ ]]></link> 
      <category><![CDATA[]]></category> 
      <author><![CDATA[jiangjianxiao]]></author> 
      <pubDate>2007-10-31 15:08:35</pubDate> 
      <description><![CDATA[
      <p>login_required 是django.contrib.auth.decorators 中的一个decorator,它的用法很简单</p><p>@login_required<br />def change_password(request):<br />&nbsp;return HttpResponse('change_password)</p><p>1. 该方法从settings中获取LOGIN_URL设置</p><p>在settings.py中增加LOGIN_URL</p><p>LOGIN_URL='/accounts/login/'</p><p>2. 该方法会传递一个添加一个next 到querystring中，这样，你可以在你的自己的login 模板中获取这个这个变量，以便在登录后重新回到登录前页面(django自带的模板会帮你处理这个，因为我使用mako 为django的模板，所以不得不自己动手处理这个)<br /></p> ]]></description>
    </item>

    <item>
      <title><![CDATA[重新启动activecontent 开发]]></title> 
      <link><![CDATA[ ]]></link> 
      <category><![CDATA[]]></category> 
      <author><![CDATA[jiangjianxiao]]></author> 
      <pubDate>2007-10-27 17:50:14</pubDate> 
      <description><![CDATA[
      <p>约一年前 ，由于各种原因，我放弃了activecontent 的开发，因为基于asp的开发受限太多，而升级到asp.net 却又不够足够吸引力而且过于笨重（我们交付过一个.net和asp互操作的升级版本，这个反响并不好）。</p><p>在拥抱动态语言后的今天，我决定重新启动activecontent的开发。我相信这段时间的思考足以让新的系统更加成熟和人性化，而python/django 也给了我足够发挥的天空。</p><p>我们将打造一个 web 2.0时代的内容系统，解决您日益复杂的建站和维护问题。如果您有兴趣，欢迎参与我们的开发过程，您的意见和参与将是我们宝贵的财富。</p><p>联系我们 :</p><p>gtalk/mail <a href="mailto:jiangjianxiao@gmail.com">jiangjianxiao@gmail.com</a> <br />msn&nbsp; <a href="mailto:jiangjianxiao@msn.com">jiangjianxiao@msn.com</a></p><p>注 activecontent 是暂用名</p> ]]></description>
    </item>

    <item>
      <title><![CDATA[ironruby 终于发布了第一个版本]]></title> 
      <link><![CDATA[ ]]></link> 
      <category><![CDATA[]]></category> 
      <author><![CDATA[jiangjianxiao]]></author> 
      <pubDate>2007-07-24 18:12:00</pubDate> 
      <description><![CDATA[
      <p>下面是几个链接</p><p>First Look at IronRuby <br /><a href="http://weblogs.asp.net/scottgu/archive/2007/07/23/first-look-at-ironruby.aspx">http://weblogs.asp.net/scottgu/archive/2007/07/23/first-look-at-ironruby.aspx</a></p><p>里面的下载地址访问不了,不过可以下载下面这个<br /></p><p>ironruby on mono</p><p><a href="http://sparcs.kaist.ac.kr/~tinuviel/download/IronRuby/">http://sparcs.kaist.ac.kr/~tinuviel/download/IronRuby/</a></p><p>&nbsp;</p><p>刚才试了rbx 控制台,完成度不高 ,连hash都不支持,不过将代码放在rb文件中,用 rbx test.rb倒是正常的</p><p>这段代码通不过</p><p>dict=Hash.new(0)</p><p>dict['a']<br />puts dict['a']<br />dict['b']='this is rb'</p><p>puts dict['b']</p><p>这段代码也通不过</p><p>line=&quot;Microsoft Visual basic&quot;</p><p>if line=~/basic/<br />&nbsp; puts &quot;has&nbsp; basic&quot;<br />end<br /></p><p>同样,这两行也通不过</p><p>puts line.sub(/basic/,&quot;test&quot;)<br />puts line.gsub(/basic/, &quot;foxpro&quot;)<br /></p><p>&nbsp;区间不行(Range类型实际上是被支持的,但each 没有提供)</p><p>('a'..'e').each{&nbsp; |char| print char}</p><p>没有upto方法<br />3.upto(6) { |i| print i}<br /></p><p>inspect/to_s &nbsp;todo </p><p>song=Song.new(&quot;bicyclops&quot;,&quot;Fleck&quot;,260)<br />print song.inspect<br />print song.to_s</p><p>&nbsp;</p><p>&nbsp;attr_reader 也是todo </p><p>&nbsp;一些重要的方法没有提供,如 Object.methods,Object.private_methods,Object.protected_methods,Object.publish_methods,Module.instance_methods等这些与自省有关的重要方法</p><p>不想再试下去了</p> ]]></description>
    </item>

    <item>
      <title><![CDATA[在Windows Forms中应用linq to sql的一些建议]]></title> 
      <link><![CDATA[ ]]></link> 
      <category><![CDATA[]]></category> 
      <author><![CDATA[jiangjianxiao]]></author> 
      <pubDate>2007-07-23 07:51:54</pubDate> 
      <description><![CDATA[
      <p><strong>此文是我在项目中应用linq to sql 的一些总结, 它正在随项目进行不断修正中,这里应该没有最正确的一说</strong></p><p>有两个决策会影响你的应用程序结构和编码</p><p>首先,你是否打算支持remoting或是webservice ,其次,你是否打算支持批量更新. 其中第一点尤为重要. </p><p><strong>支持remoting/webservice的应用结构</strong></p><p>项目通常划分为</p><p>myapplication.services&nbsp; 提供远程服务的调用<br />myapplication.models 依赖myapplication.services<br />myapplication.views 依赖myapplication.models<br />myapplication 启动应用</p><p><strong>不支持remoting/webservice应用结构</strong></p><p>myapplication.models&nbsp; 直接使用datacontext<br />myapplication.views 依赖myapplication.models<br />myapplication 启动应用</p><p>myapplication.models 通常有包括linq to sql 的数据类并分离类 ,所有的业务逻辑将在分离类中,并使用ddd 开发,或许你的应用程序现在不打算支持remoting/webservice,但需要考虑以后支持remoting/webservice,有以下几点建议</p><p>1.&nbsp;在view层,确保只使用models 层提供的方法<br />2. 在view层,最好不使用关系<br />3.<strong>总是使用ToList,ToArray等返回的结果集</strong></p><p>当使用关系导航时,虽然简洁,但依赖datacontext,因此在远程环境中windows forms比web环境更为糟糕, 因为web环境通常在一台机器上,还有个request范围可用 .</p><p><strong>DataContext的使用建议</strong></p><p>无论是否打算在remoting/webservice环境,保持在一次请求中使用和放弃DataContext是一个好的想法,如果你不想这样做,linq to sql 固有的问题也不会让使用一个长久的DataContext.比方说下面的代码(特别的,使用了自定义的关键字值</p><p>Department d=new Department();</p><p>d.Id=&quot;61&quot;;</p><p>db.Departments.Add(d);</p><p>db.SubmitChanges();</p><p>db.Departments.Remove(d);</p><p>db.SubmitChanges();</p><p>Department d2=new Department();</p><p>d2.Id=&quot;61&quot;;</p><p>db.Departments.Add(d2);</p><p>db.SubmitChanges()&nbsp;;&nbsp; //这里出现重复的关键字错误,注意这个错误不是由数据库 触发的,因为数据库中本来就已经把早先的61给删除了,这应该是datacontext内部的identity map 出错了</p><p>可以学习spring/spring.net 的template机制,创建一个DataContextTemplate类 , 让service引用这个类,如果不考虑remoting/webservice 也可以在entity基类 中并入DataContextTemplate的方法,前者的分离度会更高些,但总是需要确保entity类不会直接访问dataContext </p><p>下面是DataContextTemplate的接口设计<br />public delegate void DoInDataContext(DataContext db);<br />public delegate object DoInDataContextWithResult(DataContext db);</p><p>public interface DataContextTemplate{<br />&nbsp;&nbsp;&nbsp; void&nbsp; Find(DoInDataContext doInDataContext);<br />&nbsp;&nbsp;&nbsp; IList&lt;TEntity&gt; GetObjects&lt;TEntity&gt;(DoInDataContextWithResult callback) where TEntity : class;<br />&nbsp;&nbsp;&nbsp; TEntity GetObject&lt;TEntity&gt;(DoInDataContextWithResult callback) where TEntity : class;<br />&nbsp;&nbsp;&nbsp; IList&lt;TEntity&gt; FindAll&lt;TEntity&gt;() where TEntity : class ;<br />&nbsp;&nbsp;&nbsp; IList&lt;TEntity&gt; FindByLimit&lt;TEntity&gt;(int limit) where TEntity:class;<br />&nbsp;&nbsp;&nbsp; TEntity FindById&lt;TEntity&gt;(System.Linq.Expressions.Expression&lt;Func&lt;TEntity, bool&gt;&gt; predicate) where TEntity:class;<br />&nbsp;&nbsp;&nbsp; IList&lt;TEntity&gt; FindRelationById&lt;TEntity&gt;(System.Linq.Expressions.Expression&lt;Func&lt;TEntity, bool&gt;&gt; predicate) where TEntity:class;<br />&nbsp;&nbsp;&nbsp; IList&lt;TEntity&gt; FindByCondition&lt;TEntity&gt;(string condition,string ob,params object[] conditionParams) where TEntity:class;<br />&nbsp;&nbsp;&nbsp; void Execute(DoInDataContext&nbsp; doInDataContext);<br />&nbsp;&nbsp;&nbsp; void SubmitChanges(ChangeSet changeSet);<br />&nbsp;&nbsp;&nbsp; ChangeSet GetChangeSet(Type type);</p><p>}</p><p><br /></p><p><strong>models的设计</strong></p><p>下面总结一些共性的东西<br />1. parital 类应该实现IDataErrorInfo接口,建议将其实现为基类<br />2. 使用OnxxxChanging或是OnxxxChanged partial 方法进行数据验证<br />3. 使用OnxxxChanged partial method 进行关联更新<br />3. 如果不考虑远程,可在entity的基础类 中实现一个DataContextTemplate 的变量,如db,这样,子类就可以直接调用它<br />4. 以下是一些公共方法的签名,这些方法可以简单的借助DataContextTemplate来实现<br />FindAll 返回全部记录<br />FindById 返回该id的记录<br />FindByCondition 执行动态查询<br />FindByLimit 执行top查询<br />FindByRelation 执行关系端查询,Relation可用具体的关系端名来替代</p><p>范型方法例子(todo)</p><p><strong>关系</strong></p><p>在linq to sql 中,使用EntityRef,EntitySet来维系关系,这是因为关系端的获取可能有left outer join和lazy load等优化方式,当你放弃linq to sql的关系后 ,意味着你自己需要用传统的类型来做关系的管理.&nbsp; 其实,Table&lt;Enttiy&gt;.Attach适合远程这类环境,但 在实际的编程中,要么用要么不用,否则,编码没有一致性,会导致一些bug和以后的维护问题</p><p>&nbsp;</p><p>&nbsp;<strong>创建changeset</strong></p><p>当使用批量更新并在每次需求间请求和放弃DataContext时,客户端维护自身的ChangeSet就相当重要,ChangeSet保存了新增,修改和删除的对象,在合适的时候,比方说用户点击保存时提交.<br />当新建,改变(可跟踪bindingSource的ListChanged事件),删除时,将改变的对象写入changeset</p><p>更新时,从changeset 取出 对象进行更新<br /><br /><strong>更新顺序</strong></p><p>同数据集一样,依次处理插入,更新,删除 ,并处理好关系端,不要过分依赖submitchanges的智能判断</p><p><strong>适应ChangeSet的模型方法</strong></p><p><strong>master-detail记录</strong><br />当使用批量更新时,master并没有保存到数据库中, 但detail 通常需要 master 的主键值</p> ]]></description>
    </item>

    <item>
      <title><![CDATA[犯了一个低级错误]]></title> 
      <link><![CDATA[ ]]></link> 
      <category><![CDATA[]]></category> 
      <author><![CDATA[jiangjianxiao]]></author> 
      <pubDate>2007-07-21 16:00:05</pubDate> 
      <description><![CDATA[
      <p>最近在.net framework june ctp 下工作,使用emacs和msbuild ,结果犯了一个低级错误,即如下代码并不像我想像的那样工作</p><p>if(String.IsNullOrEmpty(error))<br />&nbsp;&nbsp;&nbsp; if( _errors.ContainsKey(propertyName))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _errors.Remove(propertyName);<br />else<br />&nbsp;&nbsp;&nbsp; &nbsp;_errors[propertyName]=error;</p><p>&nbsp;</p><p>如果在vs.net 中,这段代码被自动格式化成 </p><p>if(String.IsNullOrEmpty(error))<br />&nbsp;&nbsp;&nbsp; if( _errors.ContainsKey(propertyName))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _errors.Remove(propertyName);<br />&nbsp;&nbsp;&nbsp; else<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;_errors[propertyName]=error;</p><p>这样这个低级错误就很容易避免</p><p>本意应该是这个样子</p><p>if(String.IsNullOrEmpty(error)){<br />&nbsp;&nbsp;&nbsp; if( _errors.ContainsKey(propertyName))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _errors.Remove(propertyName);</p><p>}<br />else<br />&nbsp;&nbsp;&nbsp; &nbsp;_errors[propertyName]=error;</p><p>另外,发现在entity中实现IDataErrorInfo ,当将列表绑定 到窗体上时,IDataErrorInfo.this方法被系统调用的次数好像过了头, 这是否同我现在所采用的界面模式有关(比方说bindingsource 同时绑定到一个grid view和一个detail view)上,以后再深究他</p> ]]></description>
    </item>

    <item>
      <title><![CDATA[令我大跌眼睛的性能测试 -NET Framework 3.5 June 2007  ctp]]></title> 
      <link><![CDATA[ ]]></link> 
      <category><![CDATA[]]></category> 
      <author><![CDATA[jiangjianxiao]]></author> 
      <pubDate>2007-07-21 08:20:33</pubDate> 
      <description><![CDATA[
      <p>一直以来,我以为linq to sql 的装载性能是稍差于datatable 的,早期的测试大约是慢1到2倍,测试的记录大概是6千多.</p><p>今天早晨,在 june 2007 ctp 上的测试让我大吃一惊, 我有一个大约7万多条的报价单明细表 ,这个表我用ibatis 返回entity大约要18秒钟,用dataset大概是要4秒 (早期的测试)</p><p>今天用msbuild 在 june 2007 ctp的测试,</p><p>var list=nmis.QuotationLines.ToList() ;</p><p>居然不到 2秒, 然后用直接 返回DataTable作比较,这次分别查询20次的累计值</p><p>linq to sql : 36583&nbsp;&nbsp; 还用console输出日志</p><p>datatable : 63738</p><p>以上数据的数字大小没有意义,仅两者的比较有意义, 是不是数据量越小linq to sql 的性能就不太容易表现呢 ?(依据我早期的测试),接下来&nbsp;我又测试了6000多条 的报价单记录. 在这次测试中,我关闭了linq to sql 的log输出,并 用 具体的字段代替dattable测试查询中的*</p><p>liqn to sql : 2850</p><p>datatable: 3219</p><p>结论是不是很明显了 june ctp 版本的性能提升了</p><p>当然,如果现在要作出 linq to sql&nbsp; 性能好于 datatable(dataset) 的结论现在还是有些武断,它需要更多的测试以及不同的应用场景,希望大家也能在自己的环境中测试以下.</p><p>btw:</p><p>1. 项目是手工创建,用msbuild编译的,因为目前没有适合这个版本的vs .net ,编译为debug版本</p><p>2. 报价单/报价单_明细的数据来自实际的业务系统, 报价单有20个字段,共计6772条,报价单_明细有 25个字段,76606条记录 </p><p>3. 测试方式很简单,linq to sql 简单用ToList返回,datatable测试简单的使用select ... from ...查询</p> ]]></description>
    </item>
      
  </channel>
</rss>

