现在的位置: 首页 > 综合 > 正文

MVC学习笔记四:利用Entity Framework调用存储过程

2017年10月09日 ⁄ 综合 ⁄ 共 4344字 ⁄ 字号 评论关闭

MVC利用EF调用存储过程

这一章记录一下,如何通过EF调用数据库中的存储过程。

依然按照前面的两种数据库操作方式,一种是DbContext,第二种是ObjectContext.

在这之前,先在数据库中建立几张简单的表,方便做实例用。相关脚本如下,可供参考:
第一张表:City
USE [mydb]
GO

/****** Object:  Table [dbo].[City]    Script Date: 11/08/2013 23:06:16 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[City](
	[CityId] [int] IDENTITY(1,1) NOT NULL,
	[ChinaName] [nchar](10) NOT NULL,
	[PinYin] [nvarchar](50) NOT NULL,
	[Description] [nvarchar](50) NULL,
 CONSTRAINT [PK_City] PRIMARY KEY CLUSTERED 
(
	[CityId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

然后手工插入几条数据,这里只简单插入3条数据如下:



再建立一张商店表:Store
USE [mydb]
GO

/****** Object:  Table [dbo].[Store]    Script Date: 11/08/2013 23:11:43 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Store](
	[StoreId] [int] IDENTITY(1,1) NOT NULL,
	[StoreName] [nvarchar](50) NOT NULL,
	[CityId] [int] NOT NULL,
	[Description] [nvarchar](50) NULL,
 CONSTRAINT [PK_Store] PRIMARY KEY CLUSTERED 
(
	[StoreId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

手工插入几条数据如下,这里有7条:

最后建立一张销售表:Sale

USE [mydb]
GO

/****** Object:  Table [dbo].[Sale]    Script Date: 11/08/2013 23:14:42 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Sale](
	[Id] [int] IDENTITY(1,1) NOT NULL,
	[BusinessDate] [datetime] NOT NULL,
	[StoreId] [int] NOT NULL,
	[TotalAccount] [decimal](18, 0) NOT NULL,
 CONSTRAINT [PK_Sale] PRIMARY KEY CLUSTERED 
(
	[BusinessDate] ASC,
	[StoreId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

手工插入几条数据,如下:

好了,这里示例实现的简单功能就是:取出2013年11月1号所有店铺各自的销售金额一览。
这里需要写一个简单的存储过程,返回类似下面格式的表:


在数据库中新建一个存储过程:GetIphoneSaleDailyReport,它接受一个日期形式的参数。这里为了测试方便,指定成'2013-11-1'这一天。
use mydb
go

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:		<Author,,Name>
-- Create date: <Create Date,,>
-- Description:	<Description,,>
-- =============================================
CREATE PROCEDURE GetIphoneSaleDailyReport 
	-- Add the parameters for the stored procedure here
	@businessDate as datetime
AS
BEGIN
	-- SET NOCOUNT ON added to prevent extra result sets from
	-- interfering with SELECT statements.
	SET NOCOUNT ON;

	select CONVERT(varchar(100),a.BusinessDate,23) as 日期,aa.ChinaName as '城市',aa.StoreName as '分店',aa.Description as '分店说明',a.TotalAccount '销售总计' 
	from mydb.dbo.Sale as a
	left join (select c.ChinaName,b.StoreName,b.StoreId,b.Description from mydb..Store b inner join mydb..City c on b.CityId=c.CityId) aa
	on a.StoreId=aa.StoreId
	where a.BusinessDate=@businessDate

END
GO

可以先在数据库测试一下,看看存储过程是否新建成功:

exec GetIphoneSaleDailyReport '2013-11-1'

如果返回上面的一览表,就说明存储过程没什么问题了。


然后打开之前介绍的示例项目FirstMvcWithEF,双击打开Apples.edmx文件,鼠标右击空白处选择“从数据库更新模型”如下:
将存储过程添加到edmx文件中:
点击完成,结束添加。这时候从edmx的模型浏览器里可以看出,多出了一个存储过程,如下:
同样,再在edmx界面空白处,右击鼠标 新增 函数导入:
设置界面如下,选择之前加入的存储过程,由于存储过程返回的是一张表,这里选择复杂类型,而且系统也自动帮我创建了一个复杂类型,点击“获取列信息”可以看到存储过程返回的各种列名及其它列类型信息。
上面的准备工作已经做完,接下来介绍两种方式执行存储过程。

一.DbContext方式

如果使用的是VS2012,那么系统默认指定的可能就是这种方式。

首先,在Controllers文件夹里新建一个控制器,取名“ReportController”,在它的默认Index方法上新建一个视图。
编译项目,在Index方法上新建一个强类型的视图,但是我始终找不到上面的复杂类型“GetIphoneSaleDailyReport_Result”,在项目其它地方也引用不到它,感到很奇怪,所以这种方式就先不能实现了,如有朋友知道如何处理,可以帮忙指点下微笑

但是具体的调用存储过程是可以使用如下的方式:
public virtual IEnumerable<TEntity> GetWithRawSql(string query, params object[] parameters)
{
    return dbSet.SqlQuery(query, parameters).ToList();
}
 
public ActionResult Details(int id)
{
    var query = "exec T_Get @p0";
    return View(unitOfWork.CourseRepository.GetWithRawSql(query, id).Single());
}

二.ObjectContext方式

按照之前介绍的方式,将方式改成ObjectContext,不清楚的可以看这里,有可能还要删除Iphones.cs文件(如果之前使用DbContext遗留下来的话)。


这时候再去新建上面的Index视图时,选择强类型,就可以找到复杂属性“GetIphoneSaleDailyReport_Result”了可怜,注意模板支架选择List:



然后修改Index方法如下:
        public ActionResult Index()
        {
            mydbEntities db = new mydbEntities();

           var results = db.GetIphoneSaleDailyReport(DateTime.Parse("2013-11-1"));
            return View(results);
        }
修改对应的Index视图如下:
@model IEnumerable<FirstMvcWithEF.Entities.GetIphoneSaleDailyReport_Result>

@{
    ViewBag.Title = "Index";
}

<h2>测试存储过程</h2>

<div id="grid">
@{ 
 var grid = new WebGrid(source: Model.ToList(),
defaultSort: "分店", 
rowsPerPage: 7);
}
@grid.GetHtml(
    tableStyle: "table",
    headerStyle: "gridhead",
    alternatingRowStyle: "rowStyle",
    columns: grid.Columns(
        grid.Column("日期","日期",null,null,false),
        grid.Column("城市","城市"),
        grid.Column("分店","分店"),
        grid.Column("分店说明","分店说明"),
        grid.Column(null,"销售总计",format:@<text><input class="test-box"  id="test-box" name="test-box" type="text" value="@item.销售总计"/></text>)
   )
)
</div>
OK,编译运行,看下效果,注意视图在Report下,地址后面要加/Report:
到此,调用存储过程成功了。


抱歉!评论已关闭.