一线程序员和 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 > ;
}
catch (Exception e)
{
return false;
}
}

①执行新增、修改

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

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

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

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

相对前期判断没什么好说的,至于某笔数据检核无误后(通过A、B)条件, 添加至临时表中,新增、删除的逻辑代码是一样的,所以在Action中直接调用同一个逻辑类中的方法即可。

②执行删除

查询结果界面,可勾选多笔数据,进行删除操作,这就意味着需要往临时表中添加多笔数据。前台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) > ;
}
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 (A、B栏位为主键,TableKey栏位为联合主键,将表主键用逗号隔开后进行拼接),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('+@str+'))
)

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

4. 主管删除

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

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

执行操作,完成主管删除

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

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

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

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

    mvc项目中,解决用Url.Content方法引用jquery文件后智能提示失效的办法   这个标题不知道要怎么写才好, 但是希望文章的内容对大家有帮助. 场景如下: 我们在用开发开发程序的时候,经常 ...

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

    本文收集一些关于项目中为什么需要使用缓存功能,以及怎么使用等,在实际开发中对缓存的设计的考虑 为什么需要讨论缓存呢? 缓存是一个中大型系统所必须考虑的问题.为了避免每次请求都去访问后台的资源(例如数据 ...

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

    原文地址:http://www.cnblogs.com/snowdream/archive/2009/04/17/winforms-in-mvc.html ASP.NET MVC和WebForm各有各 ...

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

    使用UAParser在C#MVC项目中如何判断用户是在用什么设备进行访问(手机,平板还是普通的电脑) 现在我们开发的很多web应用都要支持手机等移动设备.为了让手机用户能有更加好的用户体验,我们经常为 ...

  5. 在已有的Asp.net MVC项目中引入Taurus.MVC

    Taurus.MVC是一个优秀的框架,如果要应用到已有的Asp.net MVC项目中,需要修改一下. 1.前提约定: 走Taurus.MVC必须指定后缀.如.api 2.原项目修改如下: web.co ...

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

    学习ASP.NET MVC,如果你是开发ASP.NET MVC项目的,也许你去为项目添加前ASP.NET项目的APP_Code目录,在这里创建与添加的Class类,也许你无法在MVC项目所引用. 那这 ...

  7. 如何在mvc项目中使用apiController

    文章地址:How do you route from an MVC project to an MVC ApiController in another project? 文章地址:How to Us ...

  8. 在ASP.NET MVC项目中使用极验验证(geetest)

    时间 2016-03-02 18:22:37 smallerpig 原文  http://www.smallerpig.com/979.html 主题 ASP.NET MVC   geetest开发体 ...

  9. MVC项目中,如何访问Views目录下的静态文件!

    <!--注意,是system.webServer节点,而非system.web--><system.webServer> <handlers> <add na ...

随机推荐

  1. Asp.net MVC-3-执行过程

    本篇主要讲述MVC处理请求时创建Controller和执行Action的完整过程. 创建Controller 先查看MvcHandler中处理请求的方法BeginProcessRequest: pro ...

  2. Android 动画——Frame Animation与Tween Animation

    很多手机应用的引导页都是动画的,添加动画后的应用画面会更加生动灵活,今天博主也学习了Android中Animation的使用,下面来总结下.  android中的Animation分为两种,一种是Fr ...

  3. 大数据平台常见异常-zookeeper

    本文主要阐述大数据平台环境zookeeper常见异常和解决方案 1.Connection reset by peer异常 异常说明 我们现在项目有个任务OneMinuteDataSync是用spark ...

  4. 搭建SSM项目框架全过程及思考

    1.前言 之前都是在现有框架下进行写代码或者总是看一些别人的架构,总会眼高手低.于是打算自己完整的走一遍流程,同时把所遇到的问题,思考的问题记下来,供大家参考.由于是工作年限不高,属于新手,不足之处还 ...

  5. 【转载】CANoe 入门 Step by step系列(三)简单例子的剖析

    来源:http://www.cnblogs.com/dongdonghuihui/archive/2012/09/26/2704623.html 最好的学习方式是什么?模仿.有人会问,那不是山寨么?但 ...

  6. 【菜鸟入门】安装配置eclipse 并编写运行第一个Java程序

    不得不吐槽一下,安装配置这eclipse真是太费劲了...下面总结一下,以便下次再安装 本人 win10系统,64位机 一.在官网下载eclipse安装包 文件名:eclipse-inst-win64 ...

  7. linux自动化创建补丁

    BUS #!/bin/sh #判断H5_BD_${BD_data}目录是否存在 BD_data=$(date +"%F") #当日打包多次的情况下,初始化补丁目录 if [ -d ...

  8. 服务器Hadoop+Hive搭建

    出于安全稳定考虑很多业务都需要服务器服务器Hadoop+Hive搭建,但经常有人问我,怎么去选择自己的配置最好,今天天气不错,我们一起来聊一下这个话题. Hadoop+Hive环境搭建 1虚拟机和系统 ...

  9. informatica 学习总结

    问:什么是BI? 答:BI是商务智能,它包含的应用系统和技术较宽泛,通过收集,存储,分析和提供对数据的访问,来帮助企业用户做出更好的商务决策. BI应用包括决策支持,查询和报表,联机分析处理OLAP, ...

  10. angular JS中使用jquery datatable 自定义搜索按钮点击事件 和mRender的 ng-click事件

    'use strict'; app.controller('DataTableCtrl', function ($scope, $compile) { $scope.searchFiles = { n ...