实现NBearDataSource控件 - 02-11 20:30 修订 - 新增Master/Detail实体CRUD示例

很多朋友抱怨使用 NBear时,和GridView和DetailsView等的绑定不便,为此,写了一个NBearDataSource控件,可以直接和其他DataSource一样进行绑定。

下面是一组示例,随示例包含了NBearDataSource控件和PagableRepeater控件的dll,源代码已经在NBear的V3.6.3以上版本中包含。

下载地址:http://nbear.org/download/NBearDataSourceSample.zip

本示例演示了使用NBearDataSource控件进行CRUD、使用NBearDataSource控件和NBear的强类型查询语法进行可视化查询、使用PagableRepeater控件进行数据绑定和一个典型的基于NBearDataSource的Master/Detail实体CRUD示例。大家可以看到,使用NBearDataSource的情况下,数据绑定的操作过程大大简化了。

Web.config

 1 <? xml version="1.0" ?>
 2 < configuration >
 3    < configSections >
 4     <section name="entityConfig" type="NBear.Common.EntityConfigurationSection, NBear.Common" />
 5    </ configSections >
 6    < connectionStrings >
 7     <add name="test access db" connectionString="Provider=Microsoft.Jet.OLEDB.4.0; Data Source=|DataDirectory|/DSTest.mdb" providerName="access"/>
 8    </ connectionStrings >
 9      < system .web >
10          < compilation  debug ="true"  defaultLanguage ="C#" >
11              < assemblies >
12                  < add  assembly ="System.Data.OracleClient, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
13                  < add  assembly ="System.Transactions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" /></ assemblies >
14          </ compilation >
15          < xhtmlConformance  mode ="Strict" />
16          < customErrors  mode ="Off" />
17          < authentication  mode ="None" />
18      </ system.web >
19    < entityConfig >
20      < includes >
21        <add key="Sample" value="~/EntityConfig.xml" />
22      </ includes >
23    </ entityConfig >
24 </ configuration >

第4和21行配置了EntityConfig.xml。
第7行使用nbear扩展的connectionstring配置语法设置connstr和providerName。注意这里可以使用类似的asp.net2.0下的sql2005中的|DataDirectory|来指定mdb的相对路径。(这个在标准的Access OleDb connstr语法中是不支持的,只在nbear中支持)。providerName也使用了简化语法access就是对应了Access数据库。

Default.aspx

 1 <% @ Page Language="C#"  %>
 2 <% @ Register TagPrefix="nb" Namespace="NBear.Web.Data" Assembly="NBear.Web.Data"  %>
 3 <! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
 4 < html  xmlns ="http://www.w3.org/1999/xhtml"   >
 5 < head  runat ="server" >
 6      < title > NBear DataSource Test </ title >
 7 </ head >
 8 < body >
 9 < form  id ="aspnetForm"  runat ="server" >
10      < nb:NBearDataSource  ID ="TestDS"  runat ="server"  ConnectionStringName ="test access db"
11         TypeName ="Entities.SimpleData"  FilterExpression ="{SimpleID} > 0"  DefaultOrderByExpression ="{SimpleID} DESC, {SimpleName}"   />
12      < asp:GridView  ID ="TestGrid"  runat ="server"  DataSourceID ="TestDS"  AllowSorting ="true"  AllowPaging ="true"
13         PageSize ="3"  AutoGenerateEditButton ="true"  AutoGenerateDeleteButton ="true"   />
14      < br  />
15      < asp:DetailsView  ID ="TestDetail"  runat ="server"  DataSourceID ="TestDS"  DefaultMode ="Insert"
16             AutoGenerateInsertButton ="true"  AutoGenerateRows ="false" >
17          < Fields >< asp:BoundField  DataField ="SimpleName"  HeaderText ="Name"   /></ Fields >
18      </ asp:DetailsView >
19 </ form >
20 </ body >
21 </ html >

Default.aspx没有Code Behind代码,纯粹是用asp.net 2.0的控件和NBearDataSource来CRUD。页面Default.aspx的运行效果就是,GridView可以RUD,DetailsView中可以C。

第二个页面StrongTypeQuerySample.aspx

 1 <% @ Page Language="C#" AutoEventWireup="true" CodeFile="StrongTypeQuerySample.aspx.cs" Inherits="StrongTypeQuerySample"  %>
 2 <% @ Register TagPrefix="nb" Namespace="NBear.Web.Data" Assembly="NBear.Web.Data"  %>
 3
 4 <! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
 5
 6 < html  xmlns ="http://www.w3.org/1999/xhtml"   >
 7 < head  runat ="server" >
 8      < title > NBear DataSource Test - Strong Type Query Sample </ title >
 9 </ head >
10 < body >
11      < form  id ="form1"  runat ="server" >
12    Name to Query:  < asp:TextBox  ID ="txtName"  runat ="server" ></ asp:TextBox >  (* as wild char)  &nbsp;&nbsp;
13    Order By:  < asp:DropDownList  ID ="listOrderByProperty"  runat ="server" >
14     < asp:ListItem  Selected ="True"  Text ="SimpleId"  Value ="SimpleId" ></ asp:ListItem >
15     < asp:ListItem  Text ="SimpleName"  Value ="SimpleName" ></ asp:ListItem >
16     </ asp:DropDownList >
17     < asp:DropDownList  ID ="listOrderByDesc"  runat ="server" >
18     < asp:ListItem  Selected ="True"  Text ="ASC"  Value ="ASC" ></ asp:ListItem >
19     < asp:ListItem  Text ="DESC"  Value ="DESC" ></ asp:ListItem >
20     </ asp:DropDownList >
21     &nbsp; < asp:Button  ID ="btnFind"  runat ="server"  Text ="Find"  OnClick ="btnFind_Click"   />< br  />  
22     < br  />
23      < nb:NBearDataSource  ID ="TestDS"  runat ="server"  ConnectionStringName ="test access db"
24         TypeName ="Entities.SimpleData"   />
25      < asp:GridView  ID ="TestGrid"  runat ="server"  DataSourceID ="TestDS"   />
26
27      </ form >
28     < hr  />
29 < href ="Default.aspx" > Back to Default </ a >  
30 </ body >
31 </ html >

该页面包含了一个简单的GridView和NBearDataSource和一组用于可视化查询的textbox和dropdownlist控件。

StrongTypeQuerySample.aspx.cs

 1 using  System;
 2 using  System.Data;
 3 using  System.Configuration;
 4 using  System.Collections;
 5 using  System.Web;
 6 using  System.Web.Security;
 7 using  System.Web.UI;
 8 using  System.Web.UI.WebControls;
 9 using  System.Web.UI.WebControls.WebParts;
10 using  System.Web.UI.HtmlControls;
11
12 public  partial  class  StrongTypeQuerySample : System.Web.UI.Page
13 {
14    protected void Page_Load(object sender, EventArgs e)
15    {
16
17    }

18
19    protected void btnFind_Click(object sender, EventArgs e)
20    {
21        string name = txtName.Text.Replace("*""%");
22        if (!string.IsNullOrEmpty(name))
23        {
24            TestDS.Filter(Entities.SimpleData._.SimpleName.Like(name));
25        }

26        if (listOrderByProperty.SelectedValue == "SimpleId")
27        {
28            if (listOrderByDesc.SelectedIndex == 0)
29            {
30                TestDS.OrderBy(Entities.SimpleData._.SimpleId.Asc);
31            }

32            else
33            {
34                TestDS.OrderBy(Entities.SimpleData._.SimpleId.Desc);
35            }

36        }

37        else if (listOrderByProperty.SelectedValue == "SimpleName")
38        {
39            if (listOrderByDesc.SelectedIndex == 0)
40            {
41                TestDS.OrderBy(Entities.SimpleData._.SimpleName.Asc);
42            }

43            else
44            {
45                TestDS.OrderBy(Entities.SimpleData._.SimpleName.Desc);
46            }

47        }

48    }

49}

在btnFind按钮的Click事件中,我们根据用户输入的查询条件和排序条件,使用NBearDataSource的Filter(WhereClip)和OrderBy(OrderByClip)方法进行动态查询。
注意,这两个方法个接收一个参数WhereClip/OrderByClip,它是nbear支持的强类型查询表达式参数。如示例中所示,我们可以方便的使用NBear支持的强类型查询语法指定查询条件和排序条件,如这里的line 24和line30。

简单说明一下NBearDataSource 的常用属性、方法和事件:

1、ConnectionStringName - Web.config中的connstr设置的name,可以不指定,不指定的话,默认对应web.config中的所有constr中的最后一个,类似NBear中的Gateway.Default对应最后一个connstr设置。

2、TypeName - 该DataSource承载的实体类型完整名称,必须设置。

3、FilterExpression和DefaultOrderByExpression - 可选的自定义查询条件和排序条件。{XX}表示一个实体的属性名称,NBear会在运行时将属性对应到相应的数据库字段,其他语法和sql一致。

4、Filter(WhereClip where)和OrderBy(OrderByClip orderBy)方法 - 可以运行时调用的方法,参数是nbear的强类型查询/排序表达式,调用这两个方法后,强类型表达式的值会覆盖FilterExpression和DefaultOrderByExpression属性的值。

5、Saving/Saved事件 - 这两个事件会在Insert或Update的前后被调用,并允许用户操作Save过程中的实体。


关于GridView和Repeater(DataList)如何使用NBearDataSource提供的分页支持

1、对于GridView,只需设定其PageSize、PageIndex属性即可。

2、对于Repeater(DataList)控件,只需要设置其Repeater.SelectArguments.StartRowIndex和MaximumRows属性,指定当前绑定第几页,每页页数等参数即可。不过注意Repeater的SelectArguments属性是一个protected属性,所以,可能需要继承一个自定义的Repeater,并暴露可以修改Repeater.SelectArguments的接口。

例如,如果希望绑定第5页,每页10条记录,只需要设置StartRowIndex=(5-1)*10=40, MaximumRows=10 (也就是每页记录数)。

内部实现

当指定分页信息时NBearDataSource会在内部使用Gateway.GetPageSelector().FindPage()进行数据库级别的分页查询;

如果没有指定分页信息,则NBearDataSource内部会通过Gateway.FindArray()方法进行查询,并返回所有记录。


NBearV3.6.3新增PagableRepeater控件,也就是扩展了PageSize和PageIndex属性的Repeater控件,可以直接使用该控件结合任意的支持分页的DataSource绑定某一页数据。下面是一个使用使用了这个扩展的PagableRepeater控件的示例:

PagableRepeaterSample.aspx

 1 <% @ Page Language="C#" AutoEventWireup="true" CodeFile="PagableRepeaterSample.aspx.cs" Inherits="PagableRepeaterSample"  %>
 2 <% @ Register TagPrefix="nb" Namespace="NBear.Web.Data" Assembly="NBear.Web.Data"  %>
 3
 4 <! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
 5
 6 < html  xmlns ="http://www.w3.org/1999/xhtml"   >
 7 < head  runat ="server" >
 8      < title > NBear DataSource Test - Pagable Repeater Sample </ title >
 9 </ head >
10 < body >
11      < form  id ="form1"  runat ="server" >
12      < nb:NBearDataSource  ID ="TestDS"  runat ="server"  ConnectionStringName ="test access db"
13         TypeName ="Entities.SimpleData"  DefaultOrderByExpression ="{SimpleId} DESC"   />
14      < nb:PagableRepeater  ID ="rpPagable"  runat ="server"  PageIndex ="2"  PageSize ="3"  DataSourceID ="TestDS" >
15      < ItemTemplate > SimpleId= <% Eval("SimpleId" %> , SimpleName= <% Eval("SimpleName" %> < br  /></ ItemTemplate >
16      </ nb:PagableRepeater >
17      </ form >
18     < hr  />
19 < href ="Default.aspx" > Back to Default </ a >< br  />  
20 < href ="StrongTypeQuerySample.aspx" > Strong Type Query Sample </ a >
21 </ body >
22 </ html >

Line14-16使用了PagableRepeater控件,可以看到只需要指定PageSize和PageIndex属性就行,使用非常简单。虽然这里PagableRepeater控件使用了NBearDataSource作为数据源,但实际上,也可以使用别的DataSource,只需要DataSource支持基于SelectArguments的自定义分页,比如SqlDataSource。


基于NBearDataSource的Master/Detail实体CRUD示例

MasterDetailCRUDSample.aspx

 1 <% @ Page Language="C#" AutoEventWireup="true" CodeFile="StrongTypeQuerySample.aspx.cs" Inherits="StrongTypeQuerySample"  %>
 2 <% @ Register TagPrefix="nb" Namespace="NBear.Web.Data" Assembly="NBear.Web.Data"  %>
 3
 4 <! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
 5
 6 < html  xmlns ="http://www.w3.org/1999/xhtml"   >
 7 < head  runat ="server" >
 8      < title > NBear DataSource Test - Strong Type Query Sample </ title >
 9 </ head >
10 < body >
11      < form  id ="form1"  runat ="server" >
12    Name to Query:  < asp:TextBox  ID ="txtName"  runat ="server" ></ asp:TextBox >  (* as wild char)  &nbsp;&nbsp;
13    Order By:  < asp:DropDownList  ID ="listOrderByProperty"  runat ="server" >
14     < asp:ListItem  Selected ="True"  Text ="SimpleId"  Value ="SimpleId" ></ asp:ListItem >
15     < asp:ListItem  Text ="SimpleName"  Value ="SimpleName" ></ asp:ListItem >
16     </ asp:DropDownList >
17     < asp:DropDownList  ID ="listOrderByDesc"  runat ="server" >
18     < asp:ListItem  Selected ="True"  Text ="ASC"  Value ="ASC" ></ asp:ListItem >
19     < asp:ListItem  Text ="DESC"  Value ="DESC" ></ asp:ListItem >
20     </ asp:DropDownList >
21     &nbsp; < asp:Button  ID ="btnFind"  runat ="server"  Text ="Find"  OnClick ="btnFind_Click"   />< br  />  
22     < br  />
23      < nb:NBearDataSource  ID ="TestDS"  runat ="server"  ConnectionStringName ="test access db"
24         TypeName ="Entities.SimpleData"   />
25      < asp:GridView  ID ="TestGrid"  runat ="server"  DataSourceID ="TestDS"  AllowSorting ="true"   />
26
27      </ form >
28     < hr  />
29 < href ="Default.aspx" > Back to Default </ a >< br  />   
30 < href ="PagableRepeaterSample.aspx" > Pagable Repeater Sample </ a >< br  />
31      < href ="MasterDetailCRUDSample.aspx" > Master Detail CRUD Sample </ a >
32 </ body >
33 </ html >

aspx页面为Master和Detail实体分别定一个DataSource、GridView和DetailsView。

MasterDetailCRUDSample.aspx.cs

 1 using  System;
 2 using  System.Data;
 3 using  System.Configuration;
 4 using  System.Collections;
 5 using  System.Web;
 6 using  System.Web.Security;
 7 using  System.Web.UI;
 8 using  System.Web.UI.WebControls;
 9 using  System.Web.UI.WebControls.WebParts;
10 using  System.Web.UI.HtmlControls;
11
12 public  partial  class  MasterDetailCRUDSample : System.Web.UI.Page
13 {
14    protected void Page_Load(object sender, EventArgs e)
15    {
16        dsDetails.Saving += new EventHandler<NBear.Web.Data.NBearDataSourceEventArgs>(dsDetails_Saving);
17    }

18
19    void dsDetails_Saving(object sender, NBear.Web.Data.NBearDataSourceEventArgs e)
20    {
21        Entities.Detail detail = (Entities.Detail)e.Entity;
22        if (!detail.IsAttached()) //entity.IsAttached() before inserted is false, after inserted or when updating is true.
23        {
24            detail.MasterID = int.Parse(gdMaster.SelectedRow.Cells[1].Text);
25        }

26    }

27
28    protected void gdMaster_SelectedIndexChanged(object sender, EventArgs e)
29    {
30        if (gdMaster.SelectedRow != null)
31        {
32            gdDetail.Visible = true;
33            dtDetail.Visible = true;
34            dsDetails.Filter(Entities.Detail._.MasterID == int.Parse(gdMaster.SelectedRow.Cells[1].Text));
35        }

36        else
37        {
38            gdDetail.Visible = false;
39            dtDetail.Visible = false;
40        }

41    }

42}

code-behind代码也很简单,一方面在Master的GridView事件中,改变关联的Detail的DataSource的查询条件,显示Master关联的Details;另一方面,在Detail的DataSource的Saving事件中,将Detail的MasterID属性值设为当前选中的Master的ID。这样就很容易的实现了Master和Detail的关联查询、更新和删除。


欢迎大家多提意见,我会尽可能在今后的发布时参考大家的修改意见。


02-08 22:30 修订:新增基于NBearDataSource控件的强类型查询示例
02-09 10:00 修订:增加GridView和Repeater控件如何设置并使用NBearDataSource控件提供的数据库级别分页支持绑定某页数据的说明。
02-10 15:00 修订:新增PagableRepeater控件及示例
02-11 20:30 修订:新增基于NBearDataSource的Master/Detail实体CRUD示例

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值