很多朋友抱怨使用
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)
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
<
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
<
a
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
<
a
href
="Default.aspx"
>
Back to Default
</
a
><
br
/>
20
<
a
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)
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
<
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
<
a
href
="Default.aspx"
>
Back to Default
</
a
><
br
/>
30
<
a
href
="PagableRepeaterSample.aspx"
>
Pagable Repeater Sample
</
a
><
br
/>
31
<
a
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示例