扩展SqlDataSource 1
点击次数:37 次 发布日期:2008-11-26 11:48:10 作者:源代码网
|
源代码网推荐 源代码网推荐 平时在开发过程中,通常都会涉及到数据的查看功能,比如查看订票记录,查看资料列表等。而查看这个动作,往往是跟权限有关的。 源代码网推荐 源代码网推荐 一种可能的做法是:页面上放一个GridView控件和一个SqlDataSource控件。然后在页面逻辑里加入相应操作的权限判断,然后再展现数据。或者将SqlDataSource换成ObjectDataSource,然后将权限判断封装在ObjectDataSource中。 源代码网推荐 源代码网推荐 这样做是可行的。但是存在一些问题: 源代码网推荐 权限的控制比较分散,往往需要针对某个页面编程,换一个场景,又需要做类似的工作. 源代码网推荐 权限的制止比较机械,不能适应变化,比如动态增加一个角色,并且赋予某些权限,这样页面上或者逻辑中判断该角色对某些“动作”是否具有权限时,往往比较繁琐。 源代码网推荐 SqlDataSource的SelectCommand往往是设置完成之后,只有参数值是可以变化的,其语句是不能变化的,对一些需要根据参数值创建不同SelectCommand的复杂的查询不能很好的支持。 源代码网推荐 源代码网推荐 为了解决上述问题,我们做了如下考虑: 源代码网推荐 将所有的业务逻辑操作视为一个动作,权限按动作,角色,用户分解成不同实体,存放在数据库。这样用户登陆后,可以根据当前用户身份求解到该用户对所有动作的所有权限。 源代码网推荐 将SqlDataSource进行扩展,让其支持“动作”属性,这样就可以在检索数据时,根据动作求解出当前用户需要的权限(即权限因子)。 源代码网推荐 将SqlDataSource进行扩展,让其在检索数据前,将权限因子替换掉Command中关于权限的占位符。 源代码网推荐 这样SqlDataSource检索出来的数据已经根据权限进行了过滤。 源代码网推荐 对于复杂查询,为了避免SelectCommand不能适应参数值变化的问题,我们需要动态构造SelectCommand,使其能够根据SelectParameters的不同值(通常的,我们会将参数取值空值与非空值区别对待)生成不同的SelectCommand。 源代码网推荐 源代码网推荐 OK,思路就介绍到这里,下面详细介绍一下如何扩展SqlDataSource。 源代码网推荐 源代码网推荐 SqlDataSource作为一个服务端控件,和ObjectDataSource一样,继承于DataSourceControl,具有可扩展性。 源代码网推荐 源代码网推荐 关键问题 源代码网推荐 上述思路中,不管是添加权限因子还是动态构造Sql语句,都是在执行查询数据之前,更改SelectCommand的值。所以“如何更改SelectCommand的值”是需要解决的一个问题。 源代码网推荐 源代码网推荐 另外,为了支持“权限因子”以及支持用来和SelectParameter中定义的Parameter结合,动态生成Sql的其他属性,需要给SqlDataSource扩展一些属性。 源代码网推荐 源代码网推荐 为了提供可扩展性,先实现与权限相关的扩展,然后再实现与动态生成Sql语句相关的扩展 源代码网推荐 实现SecuritySqlDataSource 源代码网推荐 和定义服务器端控件和组件一样,首先定义一个继承于Control的类,因为SqlDataSource继承于DataSourceControl,而DataSourceControl继承于Control(并且实现了IDataSource和IListSource),所以改类可以直接继承于SqlDataSource。 源代码网推荐 public class SecuritySqlDataSource : System.Web.UI.WebControls.SqlDataSource 源代码网推荐 ...{ 源代码网推荐 } 源代码网推荐 源代码网推荐 该控件需要一个SelectRefAction的属性(命名不重要)来支持“权限因子,所以在类中加入如下属性声明 源代码网推荐 protected string selectRefAction = null; 源代码网推荐 /**//// <summary> 源代码网推荐 /// SqlDataSource查询数据时,需要控制权限的动作权限名称 源代码网推荐 /// </summary> 源代码网推荐 [Category("Security"), 源代码网推荐 Description("查询数据的权限动作名称"), 源代码网推荐 ] 源代码网推荐 public string SelectRefAction 源代码网推荐 ...{ 源代码网推荐 get ...{ return this.selectRefAction; } 源代码网推荐 set ...{ this.selectRefAction = value.Trim(); } 源代码网推荐 } 源代码网推荐 源代码网推荐 其中,Category Attribute是该属性在VisualStudio可视化设计器中显示的属性分类名称。Description Attrubute是该属性在设计器中对该属性的描述。 源代码网推荐 源代码网推荐 为了让可视化编辑器将SelectRefAction设置的值保存为SqlDataSouce的属性,那么需要在类声明中用元数据属性来指示页分析器如何保存属性的值 源代码网推荐 源代码网推荐 [ParseChildren(true)] 源代码网推荐 [PersistChildren(true)] 源代码网推荐 public class SecuritySqlDataSource : System.Web.UI.WebControls.SqlDataSource 源代码网推荐 源代码网推荐 用 ParseChildrenAttribute 类指示页分析器应如何处理页上声明的服务器控件标记中嵌套的内容。以元数据属性 (Attribute) ParseChildren(true) 标记服务器控件将指示分析器把包含在服务器控件标记内的元素解释为属性 (Property)。PersistChildrenAttribute属性指示设计时是否应将 ASP.NET 服务器控件的子控件作为嵌套内部控件保持。 源代码网推荐 源代码网推荐 编译后在页面放置一个SecuritySqlDataSource,刚才设置的属性在设计器中是这样效果 源代码网推荐 源代码网推荐 保存后在设计器在SecuritySqlDataSource的属性中保存该属性的值SelectRefAction="LISTORDER"。LISTORDER即执行该查看动作的定义 源代码网推荐 源代码网推荐 然后在SelectCommand中添加权限因子 源代码网推荐 SelectCommand="SELECT [au_id], [au_lname], [au_fname], [phone], [address], [city],[state],[zip],[contract] FROM [authors] WHERE {LISTORDER} 源代码网推荐 源代码网推荐 源代码网推荐 其中where子句LISTORDER即SelectRefAction的取值。 源代码网推荐 源代码网推荐 到这里为止,关于权限的作用就通过这些声明性语句描述完了,那么怎样生成真正的权限因子呢?也就是说,如何来替换{LISTORDER}呢? 源代码网推荐 源代码网推荐 源代码网推荐 可能按照惯性思维,认为在SqlDataSource的SqlDataSource_Selecting事件中更改SelectCommand的值来更改就可以了,但是实际上是不正确的。这是因为虽然该事件在检索数据之前触发,但是在该事件中修改后的SelectCommand的值并不会被用来检索数据。因为在该事件触发之前,SelectCommand和SelectParameter已经被用来生成DBCommand,而事件触发之后,更新过的SelectCommand并不用来生成新的DBCommand。所以必须扩展SqlDataSource(真正的情况是,扩展SqlDataSourceView),使其在生成DBcommand之前就更新SelectCommand。这样就解决了如何有效修改SelectCommand的问题。同时,可以也看出:扩展一个组件,了解其本身的时序是很重要的。 源代码网推荐 源代码网推荐 详细情况如下: 源代码网推荐 通过阅读MSDN中自定义DataSourceControl的文章和反编译SqlDataSource的代码,可以发现SqlDataSource_Selecting事件不是由SqlDataSource对象触发的。 源代码网推荐 public event SqlDataSourceSelectingEventHandler Selecting 源代码网推荐 ...{ 源代码网推荐 add...{ this.GetView().Selecting += value; } 源代码网推荐 remove ...{ this.GetView().Selecting -= value; } 源代码网推荐 } 源代码网推荐 源代码网推荐 做人要厚道,请注明转自酷网动力(www.ASPCOOL.COM)。 源代码网推荐 源代码网供稿. |
