您现在的位置是:网站首页> 编程资料编程资料

在ASP.NET 2.0中操作数据之七十四:用Managed Code创建存储过程和用户自定义函数(下部分)_自学过程_

2023-05-24 404人已围观

简介 在ASP.NET 2.0中操作数据之七十四:用Managed Code创建存储过程和用户自定义函数(下部分)_自学过程_

第八步:从表现层调用Managed Stored Procedures

  当对数据访问层和业务逻辑层进行扩充以支持调用GetDiscontinuedProducts 和 GetProductsWithPriceLessThan这2种managed stored procedures后,我们可以在一个ASP.NET页面里展示这些存储过程的结果了.

  打开AdvancedDAL文件夹里的ManagedFunctionsAndSprocs.aspx页面,从工具箱拖一个GridView控件到设计器,设其ID为DiscontinuedProducts,在其智能标签里绑定到一个名为DiscontinuedProductsDataSource的ObjectDataSource控件,设置其调用ProductsBLLWithSprocs class类的GetDiscontinuedProducts方法.

//img.jbzj.com/file_images/article/201605/2016052009411333.png
图20:调用ProductsBLLWithSprocs Class类

//img.jbzj.com/file_images/article/201605/2016052009411334.png
图21:在SELECT标签里调用GetDiscontinuedProducts方法

  由于我们只需要展示产品信息,在UPDATE, INSERT,和DELETE标签里选  “(None)”,再点Finish完成配置.完成后Visual Studio会为ProductsDataTable表的列自动的添加BoundField列 或 CheckBoxField列. 将除ProductName和Discontinued以外的列全部删除.这样你的GridView 和 ObjectDataSource的声明代码看起来和下面的差不多:

  花点时间在浏览器里登录该页面。当登录时,ObjectDataSource控件将调用ProductsBLLWithSprocs class类的 GetDiscontinuedProducts方法.就像我们在第七步看到的那样,该方法又调用DAL层的ProductsDataTable class类的GetDiscontinuedProducts方法,该方法又调用存储过程GetDiscontinuedProducts.该存储过程返回那些处于“discontinued”状态的产品. 存储过程返回的结果填充到DAL层的一个ProductsDataTable,进而返回给BLL,再返回给表现层并绑定到一个GridView控件展现出来.

//img.jbzj.com/file_images/article/201605/2016052009411335.png
图22:“Discontinued”的产品被列出来了

  我们可以继续加强练习,比如在页面上再放置一个TextBox控件和一个GridView控件。在TextBox控件里输入一个数,而GridView控件调用ProductsBLLWithSprocs class类的GetProductsWithPriceLessThan方法将价格低于该数的产品展示出来.

第九步:创建并调用T-SQL UDFs

  用户自定义函数——简称UDF,是一种数据库对象,与编程语言里的函数定义很相仿.与C#里面的函数类似,UDF可以包含一系列的输入参数并返回一个特定类型的值.一个UDF要么返回标量数据(scalar data)——比如一个string, 一个integer等等;要么返回一个表列数据(tabular data).让我们先快速的考察一下这2种类型的UDF,先从标量数据类型开始.

  下面的UDF用于计算某个特定产品的总价.其有3个输入参数——UnitPrice, UnitsInStock,Discontinued.其返回一个money类型的值.它通过以UnitPrice乘以UnitsInStock来得到总价,如是处于“discontinued”状态,则总价减半.

 CREATE FUNCTION udf_ComputeInventoryValue ( @UnitPrice money, @UnitsInStock smallint, @Discontinued bit ) RETURNS money AS BEGIN DECLARE @Value decimal SET @Value = ISNULL(@UnitPrice, 0) * ISNULL(@UnitsInStock, 0) IF @Discontinued = 1 SET @Value = @Value * 0.5 RETURN @Value END 

  将该UDF添加到数据库后,我们打开Management Studio,打开Programmability文件夹,再打开Functions文件夹,再打开Scalar-value Functions文件夹,就可以看到该UDF.我们可以在一个SELECT查询里这样来使用:

 SELECT ProductID, ProductName, dbo.udf_ComputeInventoryValue (UnitPrice, UnitsInStock, Discontinued) as InventoryValue FROM Products ORDER BY InventoryValue DESC

  我已经将该udf_ComputeInventoryValue用户函数添加到了Northwind数据库。图23就是在Management Studio里调用上述SELECT查询得到的输出结果.

//img.jbzj.com/file_images/article/201605/2016052009411336.png
图23:列出了每个产品的总价

UDF也可以返回表列数据.比如,我们可以创建一个UDF返回属于某个category的所有产品:

 CREATE FUNCTION dbo.udf_GetProductsByCategoryID ( @CategoryID int ) RETURNS TABLE AS RETURN ( SELECT ProductID, ProductName, SupplierID, CategoryID, QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued FROM Products WHERE CategoryID = @CategoryID ) 

  该udf_GetProductsByCategoryID用户函数接受一个@CategoryID输入参数,返回SELECT查询的结果.一旦创建之后,该UDF就可以在SELECT查询的FROM (或 JOIN)之句里引用.下面的示例返回饮料类所属的每个产品的ProductID, ProductName,CategoryID值:

 SELECT ProductID, ProductName, CategoryID FROM dbo.udf_GetProductsByCategoryID(1)

  我已经将该udf_GetProductsByCategoryID用户函数添加到Northwind数据库。图24显示的是在Management Studio运行上述SELECT查询的结果.返回表列数据的UDF放在Table-value Functions文件夹里.

//img.jbzj.com/file_images/article/201605/2016052009411337.png
图24:饮料类产品的ProductID, ProductName,CategoryID都列出来了

  注意:关于创建和使用UDF的更多详情,请参阅文章《Intro to User-Defined Functions》和《dvantages and Drawbacks of User-Defined Functions》

第十步:创建一个Managed UDF

  上面示例里创建的udf_ComputeInventoryValue和 udf_GetProductsByCategoryID用户函数都是T-SQL数据库对象.SQL Server 2005同样支持managed UDF,我们可以将其添加到ManagedDatabaseConstructs工程,就像在第三和第五步做的那样.在这一步,我们将用managed code执行udf_ComputeInventoryValue用户函数.

  在解决资源管理器里右键单击,选择“Add a New Item”,在对话框里选User-Defined Function模板,将新UDF文件命名为udf_ComputeInventoryValue_Managed.cs.

//img.jbzj.com/file_images/article/201605/2016052009411338.png
图25:向ManagedDatabaseConstructs工程添加一个Managed UDF

  该User-Defined Function模板将创建一个名为UserDefinedFunctions的partial class类,同时还有一个方法,该方法的名字与类文件的名字一样(就本例而言,为udf_ComputeInventoryValue_Managed)。该方法有一个SqlFunction特性, 这就标明了该方法是一个managed UDF.

 using System; using System.Data; using System.Data.SqlClient; using System.Data.SqlTypes; using Microsoft.SqlServer.Server; public partial class UserDefinedFunctions { [Microsoft.SqlServer.Server.SqlFunction] public static SqlString udf_ComputeInventoryValue_Managed() { // Put your code here return new SqlString("Hello"); } } 

  该udf_ComputeInventoryValue方法目前返回一个SqlString对象,且不接受任何的输入参数.我们将对其进行更新以包含3个参数——UnitPrice, UnitsInStock,和Discontinued,并返回一个SqlMoney对象.该方法用到逻辑与上面的T-SQL类型的udf_ComputeInventoryValue用户函数的一样.

 [Microsoft.SqlServer.Server.SqlFunction] public static SqlMoney udf_ComputeInventoryValue_Managed (SqlMoney UnitPrice, SqlInt16 UnitsInStock, SqlBoolean Discontinued) { SqlMoney inventoryValue = 0; if (!UnitPrice.IsNull && !UnitsInStock.IsNull) { inventoryValue = UnitPrice * UnitsInStock; if (Discontinued == true) inventoryValue = inventoryValue * new SqlMoney(0.5); } return inventoryValue; } 

  我们注意到UDF方法的输入参数就是其对应的SQL类型:UnitPrice的类型为SqlMoney、UnitsInStock的类型为SqlInt16、Discontinued的类型为SqlBoolean.这些类型反映了这些列在Products表里定义的类型:UnitPrice列的类型为money、UnitsInStock列的类型为smallint、Discontinued列的类型为bit.

  代码首先创建了一个SqlMoney类型的名为inventoryValue的实例,并赋值为0.由于Products表允许UnitsInPrice 和 UnitsInStock列的值为NULL,因此我们首先通过SqlMoney对象的IsNull属性来检查这2列是否包NULL值。如果这2列的值都不为NULL,那么UnitPrice乘以UnitsInStock就得到了inventoryValue的值,另外如果Discontinued为true的话,inventoryValue的值减半.

  注意:由于SqlMoney对象只允许2个SqlMoney实例相乘,它不允许一个SqlMoney实例与一浮点数(literal floating-point)相乘,所以在代码里我们用一个值为0.5的SqlMoney实例与inventoryValue相乘.

第11步骤:配置Managed UDF

  现在我们已经创建了一个managed UDF,我们将把它配置给Northwind数据库.就像我们在第四步看到的那样,在解决资源管理器里,在工程名上右键单击选“Deploy”.

完成后,返回到SQL Server Management Studio,刷新Scalar-valued Functions文件夹.你就会看到2个实体:

.dbo.udf_ComputeInventoryValue——在第九步创建的T-SQL UDF

.dbo.udf ComputeInventoryValue_Managed——我们在第10步刚刚创建的managed UDF

对该managed UDF进行测试,在Management Studio里执行如下的查询:

 SELECT ProductID, ProductName, dbo.udf_ComputeInventoryValue_Managed( UnitPrice, UnitsInStock, Discontinued ) as InventoryValue FROM Products ORDER BY InventoryValue DESC 

该命令使用的是udf ComputeInventoryValue_Managed函数而不是udf_ComputeInventoryValue函数,但是输出结果都一样,可以查看图23的截屏.

第12步:调试Managed Database Objects

  在第72章我们探讨了通过Visual Studio调试SQL Server的3种模式:直接数据库调试、应用程序调试、通过SQL Server Project调试.Managed database objects不能用直接数据库模式调试,不过可以从一个客户端程序和SQL Server Project来调试.为了使调试正常工作,SQL Server 2005 数据库要求必须允许SQL/CLR调试.记得当我们最初创建ManagedDatabaseConstructs工程时,Visual Studio询问我们是否激活SQL/CLR调试(见第2步的图6).我们可以在Server Explorer窗口里在数据库上右键单击,以对该配置进行修改.

//img.jbzj.com/file_images/article/201605/2016052009411339.png
图26:确保数据库激活SQL/CLR调试

  设想我们想调试GetProductsWithPriceLessThan存储过程.我们首先要在GetProductsWithPriceLessThan方法的代码里设置断点.

//img.jbzj.com/file_images/article/201605/2016052009411340.png
图27:在GetProductsWithPriceLessThan方法里设置断点

  首先我们考察从SQL Server Project里调试managed database objects.

  由于我们的解决资源管理器里包含2个工程——ManagedDatabaseConstructs SQL Server Project以及我们的website.为了从SQL Server Project进行调试,当调试时我们需要引导Visual Studio开启ManagedDatabaseConstructs SQL Server Project.在解决资源管理器里的ManagedDatabaseConstructs project上点击右键,选“Set as StartUp Project”项.

  当从调试器打开ManagedDatabaseConstructs project时,它执行Test.sql文件的SQL statements,该文件位于Test Scripts文件夹.比如,要测试GetProductsWithPriceLessThan存储过程的话,将Test.sql文件的内容替换为下面的statement,这些statement调用GetProductsWithPriceLessThan存储过程,其输入参数@CategoryID的值为14.95:

 exec GetProductsWithPriceLessThan 14.95

  一旦将上面的脚本键入Test.sql文件,点Debug菜单里的“Start Debugging”项,或按F5或是工具栏上的绿色图标启动调试.这将在资源管理器里构建工程,将该managed database objects配置给Northwind数据库,然后执行Test.sql脚本.此时,将会遇到断点,我们可以进入GetProductsWithPriceLessThan方法,检查输入参数的值等等.

//img.jbzj.com/file_images/article/201
                <p class=提示: 本文由整理自网络,如有侵权请联系本站删除!
本站声明:
1、本站所有资源均来源于互联网,不保证100%完整、不提供任何技术支持;
2、本站所发布的文章以及附件仅限用于学习和研究目的;不得将用于商业或者非法用途;否则由此产生的法律后果,本站概不负责!

-六神源码网