在使用Entity Framework的MVC 5 Web应用程序中,我学习了如何使用db.Database.SqlQuery<model>
执行存储过程来填充索引视图,并在索引视图中显示结果。
这是我的索引视图中的相关代码(并且有效)。
// supply parameter values required by the stored procedure object[] parameters = { new SqlParameter("@campus",SqlDbType.NVarChar,3) {Value=vm.SelectedCampus}, new SqlParameter("@date1",SqlDbType.DateTime) {Value=Convert.ToDateTime(vm.SelectedStartDate)}, new SqlParameter("@date2",SqlDbType.DateTime) {Value=Convert.ToDateTime(vm.SelectedEndDate)} }; // populate the list by calling the stored procedure and supplying parameters IEnumerable<PerfOdomoeterDate> query = db.Database.SqlQuery<PerfOdomoeterDate>("PerfOdomoeterDate @campus, @date1, @date2", parameters).OrderBy(m => m.StudentName).ToList();
为了将代码放入更好的上下文中,这里是整个Index ActionResult。
private PerformanceContext db = new PerformanceContext(); private static readonly string d1 = DateTime.Now.ToShortDateString(); private static readonly string d2 = DateTime.Now.ToShortDateString(); [HttpGet] public ActionResult Index(int? page, string SelectedCampus = "CRA", string SelectedStartDate=null, string SelectedEndDate=null) { int PageNumber = (page ?? 1); PerfOdomoeterDateViewModel vm = new PerfOdomoeterDateViewModel(); vm.SelectedCampus = SelectedCampus; vm.SelectedStartDate = string.IsNullOrEmpty(SelectedStartDate) ? d1 : SelectedStartDate; vm.SelectedEndDate = string.IsNullOrEmpty(SelectedEndDate) ? d2 :SelectedEndDate; vm.CampusList = StaticClasses.ListBank.CampusList(); // supply parameter values required by the stored procedure object[] parameters = { new SqlParameter("@campus",SqlDbType.NVarChar,3) {Value=vm.SelectedCampus}, new SqlParameter("@date1",SqlDbType.DateTime) {Value=Convert.ToDateTime(vm.SelectedStartDate)}, new SqlParameter("@date2",SqlDbType.DateTime) {Value=Convert.ToDateTime(vm.SelectedEndDate)} }; // populate the list by calling the stored procedure and supplying parameters IEnumerable<PerfOdomoeterDate> query = db.Database.SqlQuery<PerfOdomoeterDate>("PerfOdomoeterDate @campus, @date1, @date2", parameters).OrderBy(m => m.StudentName).ToList(); vm.CreditTable = query.ToPagedList(PageNumber, 25); return View(vm); }
正如我所说,此代码在索引视图中完美运行。但是,在一个单独的ActionResult中,用户可以选择将数据集导出到Excel文件,我使用相同的代码,我得到了这个运行时错误:
另一个SqlParameterCollection已经包含了SqlParameter。
我的印象是每个ActionResult都在自己的范围内,所以当我从一个单独的ActionResult调用一个新查询时,我是怎么收到这个错误的?
Intellisense没有给我任何关于如何在执行存储过程后显式清空参数的线索。
这是产生错误的ActionResult中的代码。
public ActionResult ExportToExcel(string SelectedCampus, string SelectedStartDate, string SelectedEndDate) { object[] parameters2 = { new SqlParameter("@campus",SqlDbType.NVarChar,3) {Value=SelectedCampus}, new SqlParameter("@date1",SqlDbType.DateTime) {Value=Convert.ToDateTime(SelectedStartDate)}, new SqlParameter("@date2",SqlDbType.DateTime) {Value=Convert.ToDateTime(SelectedEndDate)} }; IEnumerable<PerfOdomoeterDate> query = db.Database.SqlQuery<PerfOdomoeterDate>("PerfOdomoeterDate @campus, @date1, @date2", parameters2).OrderBy(m => m.StudentName).AsEnumerable(); ...
答案 0 :(得分:2)
.Net框架向我们呈现的ADO.Net对象(如SqlParameter
,SqlCommand
等)仅仅是由真实内容构成的一层。 .Net连接池。如果我们创建一个由SqlConnection
隐式完成的新db.Database.SqlQuery
- 我们实际上并没有建立与数据库的新连接。这太昂贵了。实际上,我们的连接对象“插入”连接池中的可用连接。
通常情况下,这种机制非常透明,但它会在您看到的问题中公布。我记得曾经历过类似的问题(例外情况持续的时间超过了眼睛)。
信息是:你无法击败它,所以加入它。快速解决方案似乎是在其中一种方法中重命名参数。当然,更好的解决方案是将代码的重复部分分解为包含相同部分的方法。