ASP.NET MVC用存储过程批量添加修改数据

用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)
                            {
                                <div class="row" style="margin-top:10px">
                                    <div class="col-md-4 text-right"><span class="red">*</span> @modelMarkets.Text </div>
                                    <div class="col-md-8 text-left">
                                        <input name="text|@modelMarkets.ID" class="form-control" style="width:50%" value="@modelMarkets.TaskNum" type="text" />
                                        <input type="hidden"  name="type|@modelMarkets.ID" value="type|@modelMarkets.ID" /><!--隐藏表单-->
                                    </div>
                                </div>
                            }

  

控制器  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直接调用存储过程也不支持自定义函数。

经过测试,完美通过。

注:欢迎转载,请尊重原作者,务必标明出处和下方二维码。

时间: 02-15

ASP.NET MVC用存储过程批量添加修改数据的相关文章

ASP.NET MVC 5 - 给数据模型添加校验器

原文:ASP.NET MVC 5 - 给数据模型添加校验器 在本节中将会给Movie模型添加验证逻辑.并且确保这些验证规则在用户创建或编辑电影时被执行. 拒绝重复 DRY ASP.NET MVC 的核心设计信条之一是DRY: "不要重复自己(DRY --Don't Repeat Yourself)".ASP.NET MVC鼓励您指定功能或者行为,只做一次,然后将它应用到应用程序的各个地方.这可以减少您需要编写的代码量,并减少代码出错率,易于代码维护. 给ASP.NET MVC 和 En

在ASP.NET MVC中使用NuGet添加SignalR类库之后,再次运行程序时,它出现了一个异常:

自从在ASP.NET MVC中使用NuGet添加SignalR类库之后,再次运行程序时,它出现了一个异常: Server Error in '/' Application. The following errors occurred while attempting to load the app.- No assembly found containing an OwinStartupAttribute.- No assembly found containing a Startup or [

ASP.NET MVC 入门8、ModelState与数据验证

数据验证包括服务器端验证和客户端的验证, 本文介绍的MVC数据库端的数据验证实现. 客户端的数制验证可以使用JQuery的验证插件来实现. Html.ValidationMessage()的时候,就是从ViewData.ModelState中检测是否有指定的KEY,如果存在,就提示错误信息. ValidationMessage(modelName) 指定控件的验证错误信息; ValidationSummary() 表单所有控件的验证错误信息. 验证未通过, 目标控件和验证错误信息HTML标签,都

asp.net mvc 使用Ajax调用Action 返回数据【转】

使用asp.net mvc 调用Action方法很简单. 一.无参数方法. 1.首先,引入jquery-1.5.1.min.js 脚本,根据版本不同大家自行选择. <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script> 2.在Controllers中书写前台Ajax需要调用的Action,比如:

Asp.net mvc 使用Ajax调用Action 返回数据。

使用asp.net mvc 调用Action方法很简单. 一.无参数方法. 1.首先,引入jquery-1.5.1.min.js 脚本,根据版本不同大家自行选择. <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script> 2.在Controllers中书写前台Ajax需要调用的Action,比如:

(四)ASP.NET MVC 中 Controller 给 View 传递数据的方式

1. ViewData: 以 ViewData["keyname"] = value 这样键值对的方式进行数据传送.在对应的 cshtml 中用 @ViewData["keyname"] 来获取值. 2. ViewBag: ViewBag 是 dynamic 类型的,是对 ViewData 的一人动态类型封装,用起来更方便,和 ViewData 共同操作一个数据 .在 Controller 中使用 ViewBag.keyname=value 来赋值,在 cshtml

[ASP.NET MVC] Controlle中的Aciton方法数据接收方式

POST数据接收方式包括: 1.request.Form:(逐个获取表单提交的数据); FormCollection: [HttpPost]public async Task<string> PostSendEmail(FormCollection collection) { var a=collection["name"] return JsonConvert.DeserializeObject(obj).ToString(); } 2.同名参数:参数名称与表单元素的na

Asp.net Mvc中分部视图获取后台数据并展示

方式一: 1.主页面中代码: @{Html.RenderAction("CreateLeftMenu");} 2.Controller中代码: public PartialViewResult CreateLeftMenu() { return PartialView("PartialAdminLeft", "123"); } 这里只返回字符串"123". 3.分部视图代码: @model object @{ string s

ASP.NET MVC提交一个较复杂对象至WCF Service

前一篇<jQuery.Ajax()执行WCF Service的方法>http://www.cnblogs.com/insus/p/3727875.html 我们有练习在asp.net mvc应用程序中,POST 数据去wcf service并执行方法.本篇的练习是提交较复对象至wcf service执行方法.前一篇中,它只传递两个参数.如果我们平时开发,需要传递过多的参数时,那得需要写很多个参数.因此产生此篇,把较多个参数,创建为一个对象.然后只传递这个对象至wcf service即可. 下面