MyDataSet.Tables["TableName"]["Field"]; 简化了编程,同时不容易出错,想象一下如果在"Field"中拼错了字段名,那么编译器也不会检查出来,对于typed DataSet就不用了,如果你Field写错的话,那么马上就可以知道。
还有就是如果你在Typed DataSet包含多数据集,同时在XSD中对这些数据集建立关系和约束,那么Type DataSet会生成相应的方法来反映这些关系和约束。如果使用untyped DataSet,你需要自己做。
性能上的考虑:虽然Typed DataSet创建对象实例的时候比unTypede DataSet要多一些开销(时间和空间),但是在填充数据的时候要比untyped DataSet快,这是因为DataAdapter已经知道怎么Fill一个Typed DataSet,相比之下,DataSet需要两次读取数据库,第一次取得数据库中表的结构信息,第二次才fill数据。
Typed DataSet相对于DataSet的缺陷:除了创建的开销之外,Typed DataSet不如DataSet灵活,因为Typed DataSet一旦确定,数据表的结构就固定了,如果需要修改,必须重新生成。
而DataSet你可以随时根据需要进行操作(比如添加字段,删除字段等)。”
上面一段话的出处不可考:)下面来看怎么用vs.net创建强类型DataSet
项目-添加新项-从弹出窗口中选择数据-选择数据集,然后起一个名字,点确定。现在就可以看到设计视图了。
下一步要做的就是打开服务器资源管理器,然后找到要创建到数据集里的数据表,把它拖到设计视图中,最后shift+ctrl+b生成,一个typed DataSet就创建完毕了。
很简单吧,现在可以看看typed DataSet的后台.cs代码,推荐使用类视图来快速查看该typed DataSet的详细内容。可以看到属性方法事件一应具全,在typed DataSet里包含的原ado.net的datatable/datarow/datacolumn都是以套嵌类的方式公开的,数据库里的字段以属性方式公开
类型化的 DataSet 是从 DataSet 派生的类。同样,它继承 DataSet 的所有方法、事件和属性。此外,类型化的 DataSet 提供强类型的方法、事件和属性。这意味着可以按名称(而不是使用基于集合的方法)访问表和列。除了提高代码的可读性之外,类型化的 DataSet 还允许 Visual Studio .NET 代码编辑器自动填写您键入的行(代码智能提示,提高Coding的速度)。
此外,强类型的 DataSet 还允许在编译时对作为正确类型的值进行访问。通过强类型的 DataSet,将在编译代码时(而不是在运行时)捕获类型不匹配错误。
这里以表:"EnglishName",有字段AccountID int (PrimaryKey), FirstName varchar(30),FamilyName varchar(30)进行讲述。
第一步:生成(定义)强类型Dataset
新建一个IDE的数据库资源管理器中新建一个连接本地Northwind库,新建表EnglishName,添加字段AccountID,FirstName varchar(30),FamilyName varchar(30)然后,在IDE中新建一个Project:Project1,添加一个新的数据集类型文件EnglishNameDS.xsd。然后把表EnglishName托抓到文件EnglishName.xsd的设计器上,IDE就自动会读取表EnglishName的schema,添加表EnglishName及它的字段,无需我们一个一个输入,极大的方便了我们的数据实体定义的速度和正确性。保存EnglishNameDS.xsd,IDE将自动生成强类型DataSet:EnglishNameDS。类EnglishNameDS从DataSet继承,拥有属性EngishName(类EngishNameDataTable ),而EngishNameDataTable[Index]返回值类型为EngishNameRow,类EngishNameRow有三个属性AccountID(int),FirstName,FamilyName(string)。可以实际操作一下,查看文件EnglishNameDS.cs。
第二步:构造强类型Dataset:EnglishNameDS的对象
也许有人会疑问,我该如何把从数据库表EnglishName中查询的数据转换成EnglishNameDS的一个对象呢?
SqlHelper协助,会让代码变得非常简单 |
EnglishNameDS lds = new EnglishNameDS(); string sql = "Select * from EnglishName"; string[] tableNames = new string[]{lds.EnglishName.TableName}; SqlHelper.FillDataset(DBConnectString, CommandType.Text, sql, lds , tableNames); |
第三步:使用强类型Dataset:EnglishNameDS的对象
如果想把lds 绑定到DataGrid,非常的简单:
CREATE PROCEDURE dbo.EngishName_Insert
@AccountID int,
@FirstName nvarchar(30),
@FamilyName nvarchar(30)
AS
INSERT INTO dbo.EngishName (
AccountID,
FirstName,
FamilyName
) VALUES (
@AccountID,
@FirstName,
@FamilyName
)
IF @@ROWCOUNT = 1
RETURN @AccountID
ELSE
RETURN -100
GO
EnglishName_Update:
CREATE PROCEDURE dbo.EngishName_Update
@AccountID int,
@FirstName nvarchar(30),
@FamilyName nvarchar(30)
AS
UPDATE dbo.EngishName
SET
FirstName = @FirstName,
FamilyName = @FamilyName
WHERE
AccountID = @AccountID
IF @@ROWCOUNT = 1
RETURN @AccountID
ELSE
RETURN -100
GO
EnglishName_Delete:
CREATE PROCEDURE dbo.EngishName_Delete
@AccountID int
AS
DELETE FROM dbo.EngishName
WHERE
AccountID = @AccountID
GO
借助SqlHelper,针对Insert,Update,Delete的操作如下:
EnglishName_Insert | EnglishNameDS lds = new EnglishNameDS(); lds.EngishName.AddEngishNameRow(1000,"Zendy","Hu"); SqlHelper.ExecuteReaderTypedParams(DBConnectionString,"EnglisName_Insert",lds.EngishName[0]); |
EnglishName_Update | EnglishNameDS lds = new EnglishNameDS(); lds.EngishName.AddEngishNameRow(1000,"ZendyNew","Hu"); SqlHelper.ExecuteReaderTypedParams(DBConnectionString,"EnglisName_Update",lds.EngishName[0]); |
EnglishName_Delete | EnglishNameDS lds = new EnglishNameDS();
|
总结:
借助IDE更具Table自动生成强类型Dataset,再借助CodeSmith自动生成Insert ,Update,Delete SP,达到强类型Dataset的自定义Row类(如这里的EnglishName)属性名称和数据库中的字段名 和Insert ,Update,Delete SP参数名完全的一致( 这是关键之处),进而再借助SqlHelper的 ExecuteReaderTypedParams,就可以完全抛弃操作数据库时需要参数赋值及字段名指定等等丑陋的代码,极大的提高了代码的一致性,可读性,可维护性,简便性,正确性,也极大的减少了代码量。
也就是说,有了强类型的DataSet,及上面所述的使用方法,我的代码中从DA到UI都无需出现 Tables["TableName"]及Row[n]["FieldName"],终于键盘再也不需要敲入“字段名及表名”了,一切皆由自己掌控。
dataGrid1.SetDataBinding(lds.EnglishName,""); |
如果想要获取第一条记录的Firstname,就可以这样: string firstName = lds.EnglishName[0].FirstName. |
第四步: 使用强类型Dataset:EnglishNameDS的对象,进行Insert,Update,Delete操作。
首先利用Codesmith生成SP:
EnglishName_Insert: