- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章在ASP.NET 2.0中操作数据之七十:配置数据库连接和命令等级设置由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
导言:
在本系列我们用类型化的DataSets来构建数据访问层。就像在第一章探讨的那样,类型化DataSets的DataTables用作存储数据的“仓库”,而TableAdapters作为连接数据库的通道,以检索、修改数据.TableAdapters 将处理数据库的很多复杂的细节进行了封装,将我们解脱出来,免去了写代码连接数据库、发出命名、向DataTable填充数据的痛苦. 。
不过在某些时候我们需要深入的探究TableAdapter,直接写代码处理ADO.NET对象.在第61章《在事务里对数据库修改进行封装》里我们向TableAdapter添加了多个方法以开启、提交、回滚ADO.NET事务.这些方法都使用内在的、手动创建的SqlTransaction对象来对TableAdapter的SqlCommand对象进行赋值. 。
在本文,我们将考察如何访问TableAdapter的“数据库连接”和“数据库命令”级的设置.具体来说,我们将向ProductsTableAdapter添加函数,以访问“连接字符串”(connection string)和“命令过期时间”(command timeout)设置. 。
用ADO.NET处理数据 。
微软.NET Framework包含了很多处理数据的特殊用途的类。这些类用System.Data namespace来进行创建,其中就包括ADO.NET classe类,一些ADO.NET名下的类需要依赖某个特定的data provider才能工作.你可以想象在ADO.NET classes类和某个数据存储(data store)之间,有一个data provider充当连接通道(communication channel)以供传递信息.data provider包括OleDb 、ODBC, 以及其它一些专门设计来连接某种特定数据库系统的data provider.举个例子,我们不能用OleDb来连接一个Microsoft SQL Server数据库.而SqlClient就可以,因为它是经过优化的专门设计来连接SQL Server的. 。
当编程访问数据时,通常使用下面的模式:
1.新建数据库连接 2.发出命令 3.用SELECT查询来返回记录 。
以上3步每步都有单独的ADO.NET classes类来执行.比如连接数据库用SqlConnection class类;要发出INSERT, UPDATE, DELETE,或SELECT命令,用SqlCommand class类. 。
除了第61章《在事务里对数据库修改进行封装》外,我们都没有自己写任何ADO.NET代码,因为TableAdapters自动生成的代码包含了一些必要的功能:连接数据库、发出命令、检索数据、填充DataTables.但是有时我们要自己定制这些设置.在接下来的几步我们将探究TableAdapters内部使用的ADO.NET对象. 。
第一步:考察Connection属性 。
每个TableAdapter class类都有一个Connection属性,用于指定数据库连接信息.该属性的数据类型以及ConnectionString的值根据TableAdapter设置向导所做的配置而定.我们还记得,当向类型化的DataSet添加一个TableAdapter时,向导要我们指定数据源(见图1).在下拉列表里列出了web.config文件指定连接的数据库,以及服务器资源管理器的Data Connections里的数据库.如果我们要连接的数据库没有出现在下拉列表里,点“New Connection”按钮,以提供必需的连接信息. 。
图1:TableAdapter设置向导的第一步 。
我们化点时间来查看TableAdapter的Connection属性的代码,就像在第一章《创建一个数据访问层》里探讨的一样,我们可以在Class View窗口里查看自动生成的TableAdapter代码,转到相应的类,再双击成员名(member name)即可. 。
打开“View”菜单,选中“Class View”(或按住Ctrl+Shift+C).在Class View窗口的上半部分里,选中NorthwindTableAdapters命名空间,再选中ProductsTableAdapter class类.这将在下半部分显示出ProductsTableAdapter的成员,如图2所示.双击Connection属性以查看代码.
图2:双击Connection以查看自动生成的代码 。
TableAdapter的Connection属性以及其它与连接相关的代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
private
System.Data.SqlClient.SqlConnection _connection;
private
void
InitConnection() {
this
._connection =
new
System.Data.SqlClient.SqlConnection();
this
._connection.ConnectionString =
ConfigurationManager.ConnectionStrings[
"NORTHWNDConnectionString"
].ConnectionString;
}
internal
System.Data.SqlClient.SqlConnection Connection {
get
{
if
((
this
._connection ==
null
)) {
this
.InitConnection();
}
return
this
._connection;
}
set
{
this
._connection = value;
if
((
this
.Adapter.InsertCommand !=
null
)) {
this
.Adapter.InsertCommand.Connection = value;
}
if
((
this
.Adapter.DeleteCommand !=
null
)) {
this
.Adapter.DeleteCommand.Connection = value;
}
if
((
this
.Adapter.UpdateCommand !=
null
)) {
this
.Adapter.UpdateCommand.Connection = value;
}
for
(
int
i = 0; (i <
this
.CommandCollection.Length); i = (i + 1)) {
if
((
this
.CommandCollection[i] !=
null
)) {
((System.Data.SqlClient.SqlCommand)
(
this
.CommandCollection[i])).Connection = value;
}
}
}
}
|
当对TableAdapter class类进行“实例化”(instantiated)时,成员变量_connection的值等同为null.当访问Connection属性时,首先检查是否已经对成员变量_connection实例化,如果没有的话就调用InitConnection方法,该方法对_connection进行实例化,然后用TableAdapter设置向导指定的连接字符串对其赋值. 。
同样可以用Connection属性对一个SqlConnection对象赋值,这样的话就可以将这个新的SqlConnection对象与TableAdapter的SqlCommand对象联系起来. 。
第二步:访问“数据库连接”级的设置 。
数据库连接信息封装在TableAdapter内部,很难从应用程序的其它层对其进行访问.然而,在某些时候,某人查询、用户或ASP.NET页面需要对TableAdapter的连接信息进行访问或定制. 。
让我们对Northwind数据集的ProductsTableAdapter进行扩展,以包含一个ConnectionString属性,以便于在业务逻辑层对TableAdapter用到的连接字符串进行读取和更改. 。
注意:一个连接字符串是这样的一个字符串,它指定了数据库连接信息.比如,提供者provider、数据库的位置、身份验证,以及其它与数据库相关的设置.更多详情请参考网站ConnectionStrings.com 。
就像在第一章《创建一个数据访问层》里讨论过的一样,类型化的DataSet自动生成的类可以通过使用部分类(partial classes)来进行扩充.首先,在~/App_Code/DAL文件夹里新建一个名为ConnectionAndCommandSettings的文件夹. 。
图3:添加一个名为ConnectionAndCommandSettings的文件夹 。
在里面添加一个ProductsTableAdapter.ConnectionAndCommandSettings.cs文件,键入如下的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
using
System;
using
System.Data;
using
System.Configuration;
using
System.Web;
using
System.Web.Security;
using
System.Web.UI;
using
System.Web.UI.WebControls;
using
System.Web.UI.WebControls.WebParts;
using
System.Web.UI.HtmlControls;
namespace
NorthwindTableAdapters
{
public
partial
class
ProductsTableAdapter
{
public
string
ConnectionString
{
get
{
return
this
.Connection.ConnectionString;
}
set
{
this
.Connection.ConnectionString = value;
}
}
}
}
|
该局部类为ProductsTableAdapter class类添加了一个public类型的,名为ConnectionString的属性.该属性允许在任何层对TableAdapter用到的连接字符串进行读取和更改. 。
当创建并保存该局部类后,打开ProductsBLL class类。打开其中的一个方法,键入Adapter,再输入其范围内的一个关键字以打开智能感知,你应该可以看到这个新添加的的ConnectionString属性出现在智能感知里,这就表明了我们可以在BLL层通过编程来读取或更改其值. 。
访问整个Connection对象 。
该局部类扩展的只是connection对象众多属性中的一个:ConnectionString.如果你想在TableAdapter范围外访问整个connection对象的话,你可以改变Connection属性的保护等级.就像我们在第一步考察的那样,TableAdapter的Connection属性标明为internal,这就是说,只有在同级的类里才可以对其进行访问.不过我们可以通过TableAdapter的 ConnectionModifier属性来改变其访问范围. 。
打开Northwind数据集,在ProductsTableAdatper上右键单击,打开属性窗口,你将会看到ConnectionModifier设置为默认的Assembly. 为了在数据集范围以外访问Connection属性,我们将其改为Public. 。
图4:可以通过ConnectionModifier属性修改Connection属性的访问范围 。
保存后在返回到ProductsBLL class类,就向前面一样在某个现有的方法内键入Adapter,再输入其范围内的一个关键字以打开智能感知,你应该也可看到一个Connection属性,这意味着我们可以在业务逻辑层通过编程对连接设置进行读取或赋值操作. 。
第三步:考察与Command相关的属性 。
一个TableAdapter有一个主查询(main query),主查询默认情况下会自动生成INSERT, UPDATE,以及DELETE statements.该主查询的INSERT, UPDATE,DELETE statements在TableAdapter的代码里通过Adapter属性以一个ADO.NET data adapter object(ADO.NET数据适配器对象)的形式来执行. 由于我们的教程使用的SqlClient provider,因此Adapter属性为SqlDataAdapter类型. 。
TableAdapter的Adapter属性有3个SqlCommand类型的属性,分别用来发出INSERT, UPDATE,DELETE statements
.InsertCommand .UpdateCommand .DeleteCommand 。
一个SqlCommand对象负责向数据库发出某个具体的查询,并有相应的属性,比如:CommandText属性包含了要执行的ad-hoc SQL statement或存储过程;Parameters属性是一个SqlParameter对象集。就像我们在第一章《 创建一个数据访问层》探讨的一样,这些command对象可以通过属性窗口进行用户定制. 。
除了主查询外,TableAdapter还包含一系列的方法,当调用这些方法时,就向数据库发出具体的命令.主查询的command对象以及其它所有方法使用的command对象都保存在TableAdapter的CommandCollection属性里. 。
我们花点时间看看Northwind数据集里的ProductsTableAdapter生成的有关这2个属性及其支持的成员变量、方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
private
System.Data.SqlClient.SqlDataAdapter _adapter;
private
void
InitAdapter() {
this
._adapter =
new
System.Data.SqlClient.SqlDataAdapter();
... Code that creates the InsertCommand, UpdateCommand, ...
... and DeleteCommand instances - omitted
for
brevity ...
}
private
System.Data.SqlClient.SqlDataAdapter Adapter {
get
{
if
((
this
._adapter ==
null
)) {
this
.InitAdapter();
}
return
this
._adapter;
}
}
private
System.Data.SqlClient.SqlCommand[] _commandCollection;
private
void
InitCommandCollection() {
this
._commandCollection =
new
System.Data.SqlClient.SqlCommand[9];
... Code that creates the command objects
for
the main query and the ...
... ProductsTableAdapters other eight methods - omitted
for
brevity ...
}
protected
System.Data.SqlClient.SqlCommand[] CommandCollection {
get
{
if
((
this
._commandCollection ==
null
)) {
this
.InitCommandCollection();
}
return
this
._commandCollection;
}
}
|
Adapter 和 CommandCollection属性的代码与Connection属性的代码很相似.这些属性的get模块一开始检测相应的成员变量是否为null,如果是,那么调用一个方法,以创建这个成员变量的一个实例,然后对与command相关的属性进行赋值. 。
第四步:访问与Command相关的设置 。
理想状态下,命令级(command-level)的信息应该封装在数据访问层。当然,我们也可以通过一个部分类来对其进行扩展,就像数据库连接级(connection-level)的设置一样. 。
由于TableAdapter只有一个单一的Connection属性,所以那些用于扩展数据库连接级设置的代码是非常直观易懂的.而如果要修改命令级的设置的话要复杂一些,这是因为TableAdapter包含了多个command对象——InsertCommand, UpdateCommand,DeleteCommand, 以及CommandCollection 属性包含的数量不等的command对象.当更新命令级的设置时,这些设置需要告知所有的这些command对象. 。
比如,假如在一个TableAdapter里某些查询需要花很长的时间才能执行.当使用该TableAdapter来执行其中的一个查询时,我们可能希望增大command对象的CommandTimeout属性的值.该属性指定了等待命令执行的时间,默认为30秒. 。
想要从业务逻辑层来调整CommandTimeout属性的话,可以用我们在第二步里创建的部分类向ProductsDataTable添加一个public类型的方法,如下:(在ProductsTableAdapter.ConnectionAndCommandSettings.cs文件添加)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public
void
SetCommandTimeout(
int
timeout)
{
if
(
this
.Adapter.InsertCommand !=
null
)
this
.Adapter.InsertCommand.CommandTimeout = timeout;
if
(
this
.Adapter.DeleteCommand !=
null
)
this
.Adapter.DeleteCommand.CommandTimeout = timeout;
if
(
this
.Adapter.UpdateCommand !=
null
)
this
.Adapter.UpdateCommand.CommandTimeout = timeout;
for
(
int
i = 0; i <
this
.CommandCollection.Length; i++)
if
(
this
.CommandCollection[i] !=
null
)
this
.CommandCollection[i].CommandTimeout = timeout;
}
|
我们可以从BLL层或表现层调用该方法,以设置某个TableAdapter实例发出的所有命令的command timeout值. 。
注意:Adapter 和 CommandCollection属性被标记为private,这就意味着只能在TableAdapter内部对其访问.于Connection属性不同,我们不能改变其访问权限配置.因此,如果你想对其进行扩展以便从体系的其它层对其进行访问的话,像上面讨论的那样,我们必须使用部分类来提供一个public类型的方法或属性,对这些标记为private的命令对象进行读写操作. 。
结语:
TableAdapters将数据访问等细节进行的封装,因此我们使用TableAdapters的时候,不用关心手写ADO.NET代码以连接数据库、发出命令、用检索的数据填充DataTable等.因为它已经自动生成了这些代码. 。
但是在某些时候,我们需要定制这些ADO.NET细节,比如改变连接字符串或默认的command timeout和connection timeout的值.TableAdapter自动生成了Connection, Adapter,以及CommandCollection属性,但是默认情况下这些属性要么标记为internal要么为private.我们可以对这些内部信息进行扩展,方法就是使用部分类,在部分类里使用标记为public的方法或属性.另外,对TableAdapter的Connection属性,我们可以通过TableAdapter的ConnectionModifier属性来改变其访问权限. 。
祝编程快乐! 。
作者简介 。
本系列教程作者 Scott Mitchell,著有六本ASP/ASP.NET方面的书,是4GuysFromRolla.com的创始人,自1998年以来一直应用 微软Web技术。希望对大家的学习ASP.NET有所帮助.
最后此篇关于在ASP.NET 2.0中操作数据之七十:配置数据库连接和命令等级设置的文章就讲到这里了,如果你想了解更多关于在ASP.NET 2.0中操作数据之七十:配置数据库连接和命令等级设置的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
int enter_path(char** path) { char* standard = "./questions.txt"; printf("\n\t%s\n\t%s",
我有以下几行代码: #define PORT 9987 和 char *ptr = (char *)&PORT; 这似乎适用于我的服务器代码。但是当我在我的客户端代码中写它时,它给出了这个错误信息:
大家好,我在成员函数中有以下内容 int tt = 6; vector>& temp = m_egressCandidatesByDestAndOtMode[tt]; set& egressCandi
我知道您可以通过以下方式在正则表达式中使用 NOT 操作数: [^AB] :匹配除 "A" 之外的任何内容或"B" A(?!B) :匹配"A" ,后面不跟 "B" (?
我的代码如下,下面还解释了为什么会发生左值; typedef struct test_item { char id[MENU_NAME_LEN + NULL_SPACE]; MenuF
我正在审查一些 javascript 代码,程序员在几个地方使用了 >>。我试图在谷歌上搜索但找不到这个操作数/运算符的作用。所以我来了。下面的代码示例: var triplet=(((binarra
我使用以下行(希望这是最佳实践,如果不正确请纠正我)来处理命令行选项: #!/usr/bin/bash read -r -d '' HELP &2 for i in "${invalid_opti
我正在尝试编辑一个计时器应用程序,出现了这行代码。我该如何解决? let styleMask: Int = NSClosableWindowMask | NSTitledWindowMask 错误是:
我可以得到两个特定日期之间的差异,这将等于日期总数。现在我想将工作日除以总天数并得到整数输出。 @IBAction func go(_ sender: UIButton) { let con
我的项目有一个问题,它应该使用一个线程将每一行相加,然后将它们全部相加,但是我收到一个错误,指出左值需要作为一元 '&"操作数 pthread_create(&tid, NULL, &sum_line
我的代码有问题。有以下功能: static Poly PolyFromCoeff(int coeff); static Mono MonoFromPoly(const Poly *p, int exp
在 C# 中是否没有字符串的 OR 操作数? 我正在查看 Microsoft C# 操作数页面 - 没有关于字符串的任何类型的 OR。 我有一个要写的 if 语句: if (Convert.ToStr
下面的函数左移一个double操作数: double shl(double x,unsigned long long n) { unsigned long long* p = (unsigne
我在 Linux 中使用了以下简单的 ksh 脚本 #!/bin/ksh set -x ### Process list of *.dat files if [ -f *.dat ] then pri
我有一个使用 Entity Framework 的查询。它有许多不同的操作数,我对其优先级感到困惑。我得到了错误的结果。我需要所有 IsPaid == true 或 IsPaid == null 的记
我有以下代码来尝试创建一个约束数组以添加到 View 中: let views = ["button": button] let metrics = ["margin": 16] var constr
这个问题在这里已经有了答案: How to compare one value against multiple values - Swift (8 个答案) 关闭 6 年前。 我有一种情况,我必须
我使用 jquery $.ajax 将请求发送到服务器,它返回 JSON。 $.ajax({ url: 'moreMonth.ajax', data: { startIndex: id },
我的问题是程序没有按照“他”的预期读取代码。 我有 if (hero.getPos() == (6 | 11 | 16)) { move = new Object[] {"Up", "Righ
我在对象中创建线程时遇到问题。错误是需要作为一元“&”操作数的左值 CPP文件 #include "AirQ.h" static int i=0; AirQ::AirQ(int pinNo, bool
我是一名优秀的程序员,十分优秀!