扩展SqlDataSource 3
点击次数:26 次 发布日期:2008-11-26 11:48:08 作者:源代码网
|
源代码网推荐 源代码网推荐 那么,我们可能会放弃使用SqlDataSource,而拼凑Sql语句。 源代码网推荐 源代码网推荐 但是,拼凑Sql通常是比较繁琐的,而且在不同场景下拼凑的Sql的代码很难复用。因此扩展SqlDataSource使其能够支持这种需要,是很实用的。 源代码网推荐 源代码网推荐 那么怎样扩展才能够支持到这种需要呢? 源代码网推荐 首先,需要能够动态生成SelectCommand,而这个难点已经在SecuritySqlDataSource已经解决了。 源代码网推荐 然后,考虑到SelectParameter集合已经能够支持6种来源的Parameter(ControlParameter,CookieParameter,FormParameter,QueryStringParameter,ProfileParameter,SessionParameter)能够对不能来源的Paramter提供很好的支持,而且ControlParameter对丰富的页面控件提供很好的支持,能够避免我们通过别的解决方案解决这个问题时碰到的难题(如对TextBox控件的取值和DropDownList控件的取值是不同的),所以决定把这些参数利用起来,并且给这些已有的参数类型提供一些属性。例如:给它添加一个Pattern属性,来描述该参数的值将在SelectCommand种被Format成什么子句,来代替SelectCommand中State=@State这样的子句,简单的,Pattern值类似这样:State={0}.另外,考虑到经常碰到的动态构造子句的问题,如Title为空时,生成1=1,Title不为空时,生成au_id in (select ta.au_id from titleauthor ta where ta.title_id in (select title_id from titles where {0}))其中{0}将被Pattern的值(title={0})代替.分析这种情况,我们引入Group属性,用来将每个子查询分组。也就是每个查询参数一定属于每个组。然后在每组的查询子句构造完成后抛出一个事件SearchConditionBuilded,在事件中来构造上面的语句,这样解决了动态构造SelectCommand的问题。 源代码网推荐 再对上面的解决办法进一步优化,我们把Group属性抽取出来,变成节点,这样就不用在每个查询参数都设置Group属性,而把属于该Group组的查询参数都置于该节点之下。同时,把原来在SearchConditionBuilded事件中处理的给子查询做处理的语句抽取出来,变成一个属性,也叫Pattern。在上面举的场景中,Pattern的值就是au_id in (select ta.au_id from titleauthor ta where ta.title_id in (select title_id from titles where {0})),然后给每个组设置一个DefaultCondition,表示这个子查询中如果所有的查询参数都为空时,该子句生成的缺省条件.同时为了区别个组,给组增加一个属性Name. 源代码网推荐 所以,最后的结果是类似这样 源代码网推荐 源代码网推荐 到这里为止,前面提出的问题都已经得到了解决. 源代码网推荐 源代码网推荐 下面介绍代码如果实现 源代码网推荐 源代码网推荐 首先建立SqlDataSource类,使之继承SecuritySqlDataSource. 源代码网推荐 public class SqlDataSource : SecuritySqlDataSource 源代码网推荐 源代码网推荐 再建立SqlDataSourceView,使之继承SecuritySqlDataSourceView 源代码网推荐 SqlDataSourceView : SecuritySqlDataSourceView 源代码网推荐 源代码网推荐 Override CreateDataSourceView方法,使SqlDataSource类和SqlDataSourceView类关联起来 源代码网推荐 protected override System.Web.UI.WebControls.SqlDataSourceView CreateDataSourceView(string viewName) 源代码网推荐 ...{ 源代码网推荐 SqlDataSourceView sqlDataSourceView = new SqlDataSourceView((System.Web.UI.WebControls.SqlDataSource)this, viewName, HttpContext.Current); 源代码网推荐 return sqlDataSourceView; 源代码网推荐 } 源代码网推荐 源代码网推荐 源代码网推荐 因为需要建立一个Pattern节点,所以在SqlDataSource中增加一个属性Pattern 源代码网推荐 private SearchGroups patterns = new SearchGroups(); 源代码网推荐 [Category("Search"), 源代码网推荐 Description("查询模式"), 源代码网推荐 PersistenceMode(PersistenceMode.InnerDefaultProperty), 源代码网推荐 DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] 源代码网推荐 public SearchGroups Patterns 源代码网推荐 ...{ 源代码网推荐 get ...{ return this.patterns; } 源代码网推荐 set ...{ this.patterns = value; } 源代码网推荐 } 源代码网推荐 源代码网推荐 源代码网推荐 而Pattern属性是一个复杂节点,Pattern的属性需要被持久化成子节点,所以SqlDataSource类需要增加这两个属性 源代码网推荐 源代码网推荐 [ParseChildren(true)] 源代码网推荐 [PersistChildren(false)] 源代码网推荐 public class SqlDataSource : SecuritySqlDataSource 源代码网推荐 源代码网推荐 源代码网推荐 上面使用的SearchGroup中有一个重要的属性,它用来表示Pattern包含的组 源代码网推荐 源代码网推荐 [ParseChildren(true, "Groups")] 源代码网推荐 [TypeConverter(typeof(ExpandableObjectConverter))] 源代码网推荐 public class SearchGroups 源代码网推荐 ...{ 源代码网推荐 Private Property#region Private Property 源代码网推荐 private ArrayList groups; 源代码网推荐 #endregion 源代码网推荐 源代码网推荐 Designer Exposed InnerProperty#region Designer Exposed InnerProperty 源代码网推荐 [ 源代码网推荐 Category("Behavior"), 源代码网推荐 Description("查询组"), 源代码网推荐 NotifyParentProperty(true), 源代码网推荐 PersistenceMode(PersistenceMode.InnerDefaultProperty), 源代码网推荐 Editor(typeof(SearchGroupEditor), typeof(UITypeEditor)), 源代码网推荐 DesignerSerializationVisibility(DesignerSerializationVisibility.Content) 源代码网推荐 ] 源代码网推荐 public ArrayList Groups 源代码网推荐 ...{ 源代码网推荐 get 源代码网推荐 ...{ 源代码网推荐 if (groups == null) 源代码网推荐 ...{ 源代码网推荐 groups = new ArrayList(); 源代码网推荐 } 源代码网推荐 return groups; 源代码网推荐 } 源代码网推荐 } 源代码网推荐 #endregion 源代码网推荐 } 源代码网推荐 源代码网推荐 至于每组里的查询参数节点怎样实现,以及组节点的属性如果增加进来,由于属性较多,这里不一一解释,详细实现请参看代码 源代码网推荐 源代码网推荐 扩展中遇到的问题: 源代码网推荐 如果自定义ServerControl的类在App_Code文件夹下,则注册时不能使用Assembly,否则会出错.这是因为App_Code文件夹编译后生成的Assembly命名是随机的.正确的做法是将类单独放在一个工程里,然后引用.或者注册时使用namespace注册,不要使用Assembly 源代码网推荐 自定义SeverControl在注册时不要使用强命名,这样会使该ServerControl中的复杂节点(即包含子节点的节点)注册不正确(原因不明).可行的做法是:使用Assembly的名称即可,去掉强命名 源代码网推荐 在SqlDataSource中,如果在其定义的事件(比如Selecting,Selected)中,更改SelectCommand是无效的.这是因为真正用来取数据的DBCommand在这些事件之前已经构造完成了,而更改后的SelectCommand不会用来重新生成DBCommand. 源代码网推荐 如果这定义的ServerControl包含集合属性,那么需要扩展该集合属性的编辑器,并在集合属性上指明该编辑器Editor(typeof(EditorName)),否则编辑完成后,编辑的值不会被持久化.并且扩展的编辑器完成后,如果更改了集合的字段,那么需要重新启动IDE,设计器才会正确显示修改会的字段. 源代码网推荐 在SqlDataSource中ParameterCollection是如何求解的呢?ParameterCollection有个GetValues方法,可以求解出所有Parameter的值,结果是IOrderedDictionary类型.求解出来的结果用来构造DBCommand. 源代码网推荐 源代码网推荐 源代码网推荐 源代码网推荐 源代码网推荐 Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1489996 源代码网推荐 源代码网推荐 做人要厚道,请注明转自酷网动力(www.ASPCOOL.COM)。 源代码网推荐 源代码网供稿. |
