关于MVC项目中的主管放行

一线程序员和 sa 总是相恨相杀,这话确实不假,吐槽这里就不多讲,项目快开发完的时候,让之前各个模块的增删改操作全部都先放入对应的临时表(增加一状态栏位Status,来表示增、删、改)中,然后在主管放行界面放行之后,数据才算真正入库。sa 轻轻一句话,整个项目几乎从头到尾要改一遍。虽然已不是第一次做此事。但着实还是费了一番气力。期间遇到了不少问题很值得记录。

流程大致如上,第一排是原逻辑,第二排是增加主管放行的新逻辑(随手画的,比较简陋)

原项目中涉及到,多表主外键关系,新增范本功能等较为复杂的逻辑。这里在后面会做一个大致的流程说明

由于各表的栏位,主外键关系不同,所以第一次开发时,均是对维护的每个表(功能)建立对应的Biz(业务处理类)来实现增删改查。

新需求要求用户对数据的删、改、查操作均 添加到对应的temp表中,如   表A   栏位 B,C,D    -对应-     临时表TempA   栏位 B,C,D,Status

1 .操作某表数据

在对表进行 新增、修改、删除 操作之前,都要先到临时表中去捞取,看是否该数据已存在待主管放行的临时表中,这里可直接写一个公共方法,传表名 和 主键即可

(PS:新增、修改传入的是一笔主键值,故需要包装,两侧加单引号,删除的话,前台ajax提交时,已经添加过单引号)

        public bool IsExistTemp(string tbname, string strtablekey,string operatype)
        {
            try
            {
               //in操作 新增、修改传入值需要包装下
                if (operatype != "D")
                {
                    strtablekey = "‘" + strtablekey + "‘";
                }
                string strsql = "SELECT COUNT(*) FROM " + tbname + " AS a WHERE a.TableKey  IN(" +
                                strtablekey + ") ";
                int row = (int)base.ExecuteScalar(strsql);
                return row > 0;
            }
            catch (Exception e)
            {
                return false;
            }
        }

①执行新增、修改

新增界面点击确定、和修改界面点击确定 均是对一笔数据数据操作,直接采用Ajax的 方式,调用serializeArray()方法提交整个表单的数据 ,到Action中

对新增来说: A  判断新增的这笔数据是否已在表中存在    B  判断该笔数据是否已存在待主管放行的临时表中  C 将该数据添加至临时表中

对修改来说: A  第一次跳转至修改界面之前,先去该笔数据是否已存在待主管放行的临时表中,若在,修改界面给出提示,保存按钮为灰色不可点击

B  将该数据添加至临时表中

相对前期判断没什么好说的,至于某笔数据检核无误后(通过A、B)条件, 添加至临时表中,新增、删除的逻辑代码是一样的,一遍即可

②执行删除

查询结果界面,可勾选多笔数据,进行删除操作,这就意味着需要往临时表中添加多笔数据。前台Ajax提交时,先遍历复选框,然后将复选框勾选状态所在行的主键Key,进行包装再传递。

前面的博客中,我做的处理是循环删除,用List<string> 接受传来的主键集合,然后遍历该集合, 比较费事,这里我直接将主键进行拼接,作为一个string字符串来进行传递

KeyList.push(tabkey);

tablekeys = "‘" + KeyList.join("‘,‘") + "‘";

这样后台Action中接收的样式就是 ‘‘k1‘,‘k2‘,‘k3‘...‘

后台接收到主键拼接的字符串之后,传入 原表名称,目的表名称,主键值,目的表的Status栏位值 四个参数即可,公共方法如下

         /// <summary>
         /// 新需求-刪除(為主管放行而寫),實則將A表數據寫到B表中
         /// </summary>
         /// <param name="tbname">原表</param>
         /// <param name="tbnameTo">目的表</param>
         /// <param name="tablekeys">聯合主鍵</param>
         /// <param name="status">操作狀態(D:刪除)</param>
         /// <returns></returns>
        public bool Delete_AddTemp(string tbname, string tbnameTo, string tablekeys, char status)
        {
            try
            {
                string strsql = @"INSERT INTO " + tbnameTo + " SELECT *,‘" + status + "‘ FROM " + tbname + " WHERE TableKey IN (" + tablekeys + ")";
                //执行Sql,返回影响的行数,并判断
                return base.ExecuteNonQuery(strsql) > 0;
            }
            catch (Exception ex)
            {
                return false;
            }

        }

写到这里,关于对原表的操作,就完成了,逻辑细分下来,实际上没有多少代码量

2. 主管放行界面的查询

前面用户操作多个表之后,将数据写入到对应的Temp表中,来等待主管审批(放行\删除)。  这里查询界面写一下拉列表,选中某表,点击查询,后台返回对应的视图来显示该临时表数据,为了更好的拓展以及后期的维护,这里对应的视图目录,每一个表写一个视图,这样控制器在查询Action方法中,根据前台传的表名,返回对应表所在的View即可。查询操作比较基础,没什么值得写的。寥寥几句,叙述清楚流程即可。

3. 主管放行

主管放行这里逻辑较为复杂,遇到了不少问题,刚开始就写一存储过程,命名为sp_TableName,里面嵌入一事务,将某表的多个语句(增、删、改)寫在一起,執行成功就提交事务,失败就回滚。这样的思路的话,只需要一个表对应一个存储过程,调用时传入存储过程名, 和主键。于是乎,洋洋洒洒的将存储过程写完。极度简化后代码如下

            --刪除
            DELETE FROM A
            WHERE TableKey IN
            (SELECT TableKey FROM tempA WHERE sFlag = ‘D‘ AND TableKey IN(@str))            

            --清空臨時資源表
            DELETE FROM tempZT_SysConfig_Master WHERE TableKey IN (@str);

结果调用存储过程时候总是执行失败,在T-sql中执行存储过程是成功的,但是在MVC中调用存储过程时,老是执行返回影响行数为0,后来查看日志后发现,传入的主键参数在SQL中解析时有问题,这里主键是联合键,格式为 A,B ,MVC中调用时传入的主键为

string keys ="‘‘a1,b1‘,‘a2,b2‘,‘a3,b3‘‘";

执行到SQL中时,解析的@str 并不是  ‘‘a1,b1‘,‘a2,b2‘,‘a3,b3‘‘ ,在打开了不少web界面之后,找了一种解决方案 就是用 exec(‘‘) 将sql语句包裹起来,如下

            EXEC(‘
            --刪除
            DELETE FROM A
            WHERE TableKey IN
            (SELECT TableKey FROM tempA WHERE sFlag = ‘‘D‘‘ AND TableKey IN(‘+@str+‘))            

            --清空臨時資源表
            DELETE FROM tempZT_SysConfig_Master WHERE TableKey IN (‘+@str+‘);
            ‘)

总算解决了,后来在测试中又遇到了新问题,主外键约束,由于原表中存在主外键约束,而对应的临时表Temp是没有主外键关系的,如果有的话,主次颠倒不少,逻辑就更加复杂而且无效

从表新增约束

假如某用户登录系统后对主表A增加几笔数据,然后在从表B中添加了几笔对应的数据,当主管放行临时表B的这笔数据时,由于主管还没放行临时表A的这笔数据,所以执行时就会异常。

这里只需要给一提示,请先放行主表中的新增数据即可,查询是否有从表新增约束的核心sql 如下,判断返回值是否大于0 即可。

SELECT COUNT(a.TableKey) FROM(
SELECT distinct b.TableKey FROM tempMainA AS a
INNER JOIN tempMinorA AS b ON a.s1 = b.s1
AND a.s2 = b.s2 ) AS a
WHERE a.TableKey IN(@tablekeys)

主表删除约束

假如某用户登录系统后对主表删除几笔数据,当主管放行临时表此批数据时,调用存储过程执行到对应的删除T-SQl语句时,由于外键约束,从表对应的数据还在,所以就会报异常

这里主需要在存储过程中删除语句的sql上面,写入删除从表的sql即可。不过这里由于表的特殊性,在获取从表主键时着实下了不少功夫,删除从表的SQL如下:

--刪除從表
DELETE FROM Minor WHERE TableKey IN(
       SELECT a.TableKey FROM Minor AS a WHERE substring(a.TableKey,1,len(a.TableKey) - CHARINDEX(‘‘,‘‘,reverse(a.TableKey))) IN(
              SELECT TableKey FROM tempMain WHERE status = ‘D‘ AND TableKey IN(‘[email protected]+‘))
 )

从表联合主键为 ‘a1,a2,a3‘  , 主表联合主键为 ‘a1,a2‘ ,所以先捞取执行删除操作的主表的联合主键 tablekey(第三行),然后通过截取从表的联合主键Tablekey in (第二行)得到从表需要删除的TableKey,最后执行删除从表操作.

4. 主管删除

关于主管删除 ,其实就是清空Temp表的记录。对于放行来说,其逻辑就相当的简单,没有必要去循环删除,直接如上操作,后台接收前台传入主键拼接后的string字符串和表名,然后在逻辑类中写入delete的T-sql即可

DELETE FROM  " + tbname + "  WHERE TableKey IN(" + tablekeys+ ")

执行操作,完成主管删除

总结:写到这里,关于主管放行的简体版本的大致流程已经叙述完了,说白了,放行实际上就是将 临时表的数据剪切至原表,没错,就是剪切,实现剪切操作时,T-SQL的能力要有,自认为我的水平远不如老大,原项目中本来我就写有对数据的删、改、增操作。所以我第一次的思路是主管放行时,一笔一笔的去执行,传入实体,调用原始的删、改、增方法。这样效率低不说,传入实体的逻辑写起来也相当费劲。最后在老大手把手的教授下,通过存储过程可放行临时表中所有勾选的数据,着实提高了效率。

---市人皆大笑,举手揶揄之

时间: 2024-10-05 10:42:08

关于MVC项目中的主管放行的相关文章

谈谈MVC项目中的缓存功能设计的相关问题

本文收集一些关于项目中为什么需要使用缓存功能,以及怎么使用等,在实际开发中对缓存的设计的考虑 为什么需要讨论缓存呢? 缓存是一个中大型系统所必须考虑的问题.为了避免每次请求都去访问后台的资源(例如数据库),我们一般会考虑将一些更新不是很频繁的,可以重用的数据,通过一定的方式临时地保存起来,后续的请求根据情况可以直接访问这些保存起来的数据.这种机制就是所谓的缓存机制. 根据缓存的位置不同,可以区分为: 1.客户端缓存(缓存在用户的客户端,例如浏览器) 2.服务器断货(缓存在服务器中,可以缓存在内存

在VS2013 MVC项目中上传图片

之前做网站项目时,凡遇到保存图片的,我都将图片上传后存储在服务器的本地文件夹中,在一个Controller的Action中,类似操作如下所示: public ActionResult UpLoad(HttpPostedFileBasearImg) {             //保存图片            if (arImg != null)            {                 string uploadName =arImg.FileName;//获取待上传图片的完整

MVC项目中如何判断用户是在用什么设备进行访问

使用UAParser在C#MVC项目中如何判断用户是在用什么设备进行访问(手机,平板还是普通的电脑) 现在我们开发的很多web应用都要支持手机等移动设备.为了让手机用户能有更加好的用户体验,我们经常为手机设备专门准备一套前端的页面.这样当用户使用普通电脑来访问的时候,我们的应用就向用户展示普通电脑的页面.当用户使用手机等移动设备来访问我们的系统的时候,我们就向用户展示手机设备的页面.但是这时候另一个问题出现了.如何判断用户在使用什么设备访问我们的应用?是使用手机还是普通电脑? 网上能查到的不同的

在 ASP.NET MVC 项目中使用 WebForm、 HTML

原文地址:http://www.cnblogs.com/snowdream/archive/2009/04/17/winforms-in-mvc.html ASP.NET MVC和WebForm各有各的优点,我们可能需要同时使用ASP.NET MVC和WebForm.本文介绍了如何在ASP.NET MVC项目中使用WebForm.首先新建一个名为WebForms的文件夹用于存放WebForm,并添加一个Web窗体文件Demo.aspx作为演示. Demo.aspx就简单的输出一句话“It’s a

转 mvc项目中,解决引用jquery文件后智能提示失效的办法

mvc项目中,解决用Url.Content方法引用jquery文件后智能提示失效的办法 这个标题不知道要怎么写才好, 但是希望文章的内容对大家有帮助. 场景如下: 我们在用开发开发程序的时候,经常会引用jquery, 但是由于路由的关系,最终访问页面的地址相对js文件来说,是不固定的. 为了在view中能够引用到jquery文件,我们通常都是用如下的代码 <script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")

【转】在 ASP.NET MVC 项目中使用 WebForm

ASP.NET MVC和WebForm各有各的优点,我们可能需要同时使用ASP.NET MVC和WebForm.本文介绍了如何在ASP.NET MVC项目中使用WebForm. 首先新建一个名为WebForms的文件夹用于存放WebForm,并添加一个Web窗体文件Demo.aspx作为演示. Demo.aspx就简单的输出一句话"It's a WebForm." 关键步骤在于路由设置.如果你希望WebForms这个文件夹名作为URL的一部分,也就是普通WebForm应用程序的方式来访

ServiceStack 项目实例 005 使用第一个服务功能 (在MVC项目中)

建立好服务后,我们就可以在MVC项目中使用这个服务,在使用这个服务之前,需要先确定一下它所在端口,只需要在SS项目上点右键,将其设置为启动项目,然后运行一下SS项目,在浏览器地址栏,就可以看到这个服务的端口号,并且也能看到已经添加到其中的服务.(运行的效果可以在001节中的截图看到,001节中的端口为59068.) 在MVC的Controller目录下添加一个控制器NewsController.cs,在NewsController.cs中加入一个 Action, 用来显示添加新闻的页面 publ

添加Bootstrap 到MVC项目中(vs2010)

环境:Visual Studio 2010   ASP.NET MVC3 手动添加: 下载地址:http://twitter.github.com/bootstrap/ 一个js,两个css,两张图 js 文件:  •bootstrap.min.js CSS 文件:  •bootstrap.min.css  •bootstrap-responsive.min.css image 文件:  •glyphicons-halflings.png  •glyphicons-halflings-white

ASP.NET MVC项目中App_Code目录在程序应用

学习ASP.NET MVC,如果你是开发ASP.NET MVC项目的,也许你去为项目添加前ASP.NET项目的APP_Code目录,在这里创建与添加的Class类,也许你无法在MVC项目所引用. 那这样说,是不是一没有作用了呢?非也. 从下面一步一步来学习. 创建一个model,名称:Machine using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace Insu