Entity Framework 6 Recipes 2nd Edition(10-2)译 -> 返回输出参数
10-2. 返回输出参数
问题
想获取存储过程里的一个或多个输出参数的值
解决方案
假设我们有一个像Figure 10-1所示的,出租车辆与租金收入的模型
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
kid1412声明:转载请把此段声明完整地置于文章页面明显处,并保留个人在博客园的链接:http://www.cnblogs.com/kid1412/(可点击跳转)。