用 Entity Framework 进行数据库交互,在代码里直接用 lamda 表达式和 linq 对数据库操作,中间为程序员省去了数据库访问的代码时间,程序员直接可以专注业务逻辑层的编写。但是对于比较复杂的表关系关联查询或者修改就比较费劲了。通常可以采用的方式是用 EF 执行 SQL 语句或者 "存储过程",特别是执行复杂批量任务,当然也可以在 MVC 底层用 ADO.NET,这里就不多说了。怎么做批量呢?这里讲讲在 EF 下用存储过程批量添加修改数据。
需求是这样的:需要批量添加修改产品类别的投放任务数额,每月更新一次,月初归 0,添加后会显示在表单中,也就是添加修改都在一个页面。
思路:前端先用表单把类别动态读取出来,用 viewbag 动态加载到页面,如果已经有添加当月任务数,就读取出来显示到表单上,可以进行修改,否则就是全新添加当月任务数。提交表单的时候出现了个问题,怎么把类别编号 post 到后台,我想了一个办法,那就是加一个隐藏域,值为 "Type | 类别编号",后台取数据是判断是否包含 Type 来判断是否是类别编号,然后用 split('|')[1] 循环读取。
怎么传递到数据库呢?我把数据存到 datatable 里面,然后用 EF 执行存储过程,把 datatable 当着参数传到数据库处理。
数据库怎么处理这个 datatable 呢?用自定义数据类型处理
代码步骤:
控制器 显示动态表单
- public ActionResult MarketTaskAdd() {
- var markeType = new MarketDataProvider().GetBTIDData().Where(a = >a.ID != "0"); //读取类别
- var rel = new MarketTaskProgressProvider().GetMarketMonthTask();
- if (rel.Count() > 0) {
- ViewBag.datas = rel.Join(markeType, a = >a.MKBTID, b = >int.Parse(b.ID), (a, b) = >new {
- a.MKBTID,
- b.ID,
- b.Text,
- a.TaskNum
- }).Select(s = >new ViewsModel {
- ID = s.MKBTID.ToString(),
- Text = s.Text,
- TaskNum = s.TaskNum.ToString()
- });
- } //如果有数据关联数据
- else {
- var rel2 = markeType.Select(s = >new ViewsModel {
- ID = s.ID,
- Text = s.Text,
- TaskNum = ""
- }).ToList(); //直接返回表单
- ViewBag.datas = rel2;
- }
- return View();
- }
开始想直接返回 object,结果前台遍历不支持,故新建实体类 ViewsModel。
View 页面
- @foreach (var modelMarkets in ViewBag.datas)
- {
- * @modelMarkets.Text
- " class="form-control" style="width:50%" value="@modelMarkets.TaskNum" type="text" />
- " value="" />
- }
控制器 post 提交表单
- [HttpPost]
- public ActionResult MarketTaskAdd(string type)
- {
- var strform = Request.Form;
- int userId = adminUser!=null?adminUser.UserID:0;//创建人或者修改人ID
- DataTable dt = new DataTable();
- dt.Columns.Add("MKBTID",Type.GetType("System.Int32"));
- dt.Columns.Add("TaskNum", Type.GetType("System.Int32"));
- List<string> temp1 = new List<string>();
- List<string> temp2 = new List<string>();
- for (int i = 0; i < strform.Count; i++)
- {
- if (strform[i].Contains("type"))
- { temp1.Add(strform[i].Split('|')[1]); }
- else
- { temp2.Add(strform[i]); }//循环分解表单
- }
- for (int i = 0; i < temp1.Count; i++)
- {
- DataRow dr = dt.NewRow();
- dr[0] = temp1[i];
- dr[1] = temp2[i];
- dt.Rows.Add(dr);//批量添加到datatable
- }
- var rel = new MarketTaskProgressProvider().MarketTaskAddOrEdit(userId,dt);//调用方法
- if(rel)
- ViewBag.js = "<script>alert('操作成功!');window.location.href='/MarketTaskProgress/MarketTaskAdd';</script>";
- else
- ViewBag.js = "<script>alert('操作失败!');window.location.href='/MarketTaskProgress/MarketTaskAdd';</script>";
- List<ViewsModel> listTemp = new List<ViewsModel>();
- listTemp.Add(new ViewsModel
- {
- ID = "",
- Text = "",
- TaskNum = ""
- });
- ViewBag.datas = listTemp;
- return View();
- }
- }
提交到数据库方法:
- public bool MarketTaskAddOrEdit(int userId,DataTable dt)
- {
- using (DssEntity entity = new DssEntity())//不推荐用using
- {
- SqlParameter p = new SqlParameter("@CreatedUser",DbType.Int32);
- p.Value = userId;
- SqlParameter p1 = new SqlParameter("@tableMarketTask",DbType.Object);
- p1.Value = dt;
- p1.TypeName = "tableMarketTask";//参数处理,貌似自定义函数必须加这个函数名称
- var rel = entity.Database.ExecuteSqlCommand("EXEC[dbo].[PR_MarketTaskAddorEdit] @CreatedUser,@tableMarketTask", p,p1);//ef执行存储过程
- return rel > 0;
- }
- }
首先根据情况建自定义类型,如下
- -- Create the data type
- CREATE TYPE [dbo].[tableMarketTask] AS TABLE(
- [MKBTID] [varchar](50) NOT NULL,--投放类别
- [TaskNum] [varchar](50) NOT NULL--投放任务数量
- )
也可以用 sql server 工具手动新建
第二是建存储过程
- CREATE PROCEDURE PR_MarketTaskAddorEdit
- @CreatedUser INT,
- @tableMarketTask tableMarketTask readonly --自定义类型的参数,必须加readonly。
- AS
- DECLARE @TempCreatedUser INT
- IF EXISTS(SELECT TOP 1 * FROM MarketMonthTask T WHERE Months=MONTH(GETDATE()))--当月存在的话就修改
- BEGIN
- SELECT TOP 1 @TempCreatedUser=CreatedUser FROM MarketMonthTask T WHERE Months=MONTH(GETDATE())
- DELETE FROM MarketMonthTask WHERE Months=MONTH(GETDATE())
- INSERT INTO MarketMonthTask(MKBTID,TaskNum,Months,UpdateUser,CreatedUser) SELECT MKBTID,TaskNum,MONTH(GETDATE()),@CreatedUser,@TempCreatedUser FROM @tableMarketTask
- END
- ELSE--或者直接插入
- BEGIN
- INSERT INTO MarketMonthTask(MKBTID,TaskNum,Months,CreatedUser) SELECT MKBTID,TaskNum,MONTH(GETDATE()),@CreatedUser FROM @tableMarketTask
- END
自定义类型可以像表那样自己查询,很方便。自定义函数不容易调试。EF 直接调用存储过程也不支持自定义函数。
经过测试,完美通过。
来源: http://www.bubuko.com/infodetail-1946283.html