Entity Framework 6 Recipes 2nd Edition(10-2)译 -> 返回输出参数

时间:2021-02-10 02:45:48

10-2. 返回输出参数

问题

想获取存储过程里的一个或多个输出参数的值

解决方案

假设我们有一个像Figure 10-1所示的,出租车辆与租金收入的模型

Entity Framework 6 Recipes 2nd Edition(10-2)译 -> 返回输出参数

Figure 10-1.出租车辆与租金收入的模型

我们想知道在指定日期里,收入了几笔租金和金额, 以及车辆的租凭情况. 存储过程Listing 10-7 就是获取这些信息的.

Listing 10-7. A Stored Procedure for the Vehicles Rented, the Number of Rentals, and the Total Rental Payments

create procedure [chapter10].[GetVehiclesWithRentals]

(@date date,

@TotalRentals int output,

@TotalPayments decimal(18,2) output)

as

begin

select @TotalRentals = COUNT(*), @TotalPayments = SUM(payment)

from chapter10.Rental

where RentalDate = @date

select distinct v.*

from chapter10.Vehicle v join chapter10.Rental r

on v.VehicleId = r.VehicleId

end

为了在模型里使用空上存储过程,执行以下操作:

1. 右击模型的设计视图,选择“从数据库更新模型”. 在对话框里

,选择存储过程GetVehiclesWithRentals. 点击“完成”添加存储过程到模型里。

2. 右击模型的设计视图, 选择“新增”➤“函数导入”. 在“存储过程/函数名称(P):”下拉框里选择

GetVehiclesWithRentals,在“函数导入名称(F):”里输入GetVehiclesWithRentals (这个就是在模型里生成的方法名称)。在“返回以下内容的集合”里勾选“实体”,并从下拉列里选择Vehicle

.点击“确定”

3.下面的Listing 10-8 就是使用GetVehiclesWithRentals的方法.

Listing 10-8.通过GetVehiclesWithRentals() 方法使用模型里的GetVehiclesWithRentals存储过程

staticvoid Main(string[] args)

{

using (var context = newEFRecipesEntities())

{

context.Database.ExecuteSqlCommand("delete from chapter10.Rental");

context.Database.ExecuteSqlCommand("delete from chapter10.Vehicle");

var car1 = newVehicle { Manufacturer = "Toyata", Model = "Camry", Year = 2013 };

var car2 = newVehicle { Manufacturer = "Chevrolet", Model = "Corvette", Year = 2013 };

var r1 = newRental { Vehicle = car1, RentalDate = DateTime.Parse("5/7/2013"), Payment = 59.95m };

var r2 = newRental { Vehicle = car2, RentalDate = DateTime.Parse("5/7/2013"), Payment = 139.95m };

car1.Rentals.Add(r1);

car2.Rentals.Add(r2);

context.Vehicles.Add(car1);

context.Vehicles.Add(car2);

context.SaveChanges();

}

using (var context = newEFRecipesEntities())

{

string reportDate = "5/7/2013";

var totalRentals = newObjectParameter("TotalRentals", typeof(int));

var totalPayments = newObjectParameter("TotalPayments", typeof(decimal));

var vehicles = context.GetVehiclesWithRentals(DateTime.Parse(reportDate),

totalRentals, totalPayments);

Console.WriteLine("Retal Activity for {0}", reportDate);

Console.WriteLine("Vehicles Rented");

foreach (var vehicle in vehicles)

{

Console.WriteLine("{0} {1} {2}", vehicle.Year, vehicle.Manufacturer, vehicle.Model);

}

Console.WriteLine("TotalRentals:{0}", (int)totalRentals.Value);

Console.WriteLine("Total Payments:{0}", ((decimal)totalPayments.Value).ToString("C"));

Console.WriteLine("\npress any key to exit...");

Console.ReadKey();

}

}

以下Listing 10-8是控制台输出结果:

===================================================================

Rental Activity for 5/7/2013

Vehicles Rented

2013 Toyota Camry

2013 Chevrolet Corvette

Total Rentals: 2

Total Payments: $200.00

===========================================

它是如何工作的?

第2步操作会使用GetVehiclesWithRentals存储过程更新模型 ,我们也更新了概念模型,让存储过程暴露在GetVehiclesWithRentals()上,该方法与存储过程有着类似的签名.

有一点请注意:当调用GetVehiclesWithRentals()方法后,它返回的实体集必须先实例化,输出参数才可以用。这跟ADO.NET里的DataReader相似,DataReader必须必执行NextResult(),才能读取到数据。同样地,实体集必须被访问或是处理之后,输出参数里才能有输出值。

在我们例子里, 当我们实例化第一个vehicle后,输出参数还不可以用,如果我们把输出payments和rentals总和的代码(Console.WriteLine("TotalRentals:{0}", (int)totalRentals.Value);Console.WriteLine("Total Payments:{0}",((decimal)totalPayments.Value).ToString("C"));)移动到foreach循环里,执行到这里的时候,会产生异常(totalRentals.Value和totalPayments.Value为null). 另一种解决办法是:我们把实体类集用ToList()方法实例化之后,然后循环实例化后的实体集. 这样我们也就可以在foreach循环里使用这两个输出参数的输出值了。

附:创建示例用到的数据库的脚本文件

totalPayments