zoukankan      html  css  js  c++  java
  • 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="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直接调用存储过程也不支持自定义函数。

    经过测试,完美通过。

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

  • 相关阅读:
    判断鼠标在按钮区域上面
    在MFC下绘制直线,使用橡皮筋技术,可以使直线效果跟随鼠标移
    三缓冲
    MFC--自己优化滚动条的双缓冲绘图方法
    MFC视图切换大全总结
    各种线程:事件、互斥量、信号量、临界区 的用法,我自己做的,有用,附件里面有,博客附件里面有
    http://www.cctry.com/forum.php?mod=viewthread&tid=800&reltid=4131&pre_thread_id=0&pre_pos=3&ext=
    关于Mac下pycharm无法调用摄像头权限的问题
    终于理解清楚attention,利用attention对黄金价格进行预测
    tensorboard在colab中的实现
  • 原文地址:https://www.cnblogs.com/xbhp/p/6403961.html
Copyright © 2011-2022 走看看