其实,关于事务,锁,锁粒度虽不是很熟练但起码是明白掌握了。但是,发现msdn中有关的描述与前两本书不是很一致,至少在用语上。所以现在迷惑的无从下手了。
目前的情况,使用sqlcommand 来执行sql语句没有问题。执行存储过程也没有问题了。
但是在加锁,并发,批量插入更新时就有问题了。下面是具体问题。
问题1 == 库存期初数据的录入。
一般情况下,录入与修改已录过的数据在操作上是同时的。拿我用过的用友的产品为例。
点击菜单的修改按钮后,可以实际开始操作。在一个二维表格中,按行录入数据。点击保存后,这些记录将在验证后插入数据库。
但是,我们是不知道每次会录入多少条的。我用sqlcommand每次只能插入一条。所以,不知大家是用的什么来做,需要作自定义控件吗?
问题2 ==库存期初的修改与录入同时。
与问题1类似,有时候在录入新记录的时候会修改几条旧的。同样不知道修改了多少条旧的,录入多少新的。这回,不光有insert 还有update。
该如何处理。
问题3:==问题1 和问题2在 较多人并发的状态下如何做呢??因为一般会很多人为了赶进度同时录入的。
问题4==录入业务单据的时候,比如发货单。一般后台表都是两个,一个主表,一个子表。主表记录单机头的信息。子表记录具体明细记录。两个表是靠单据编号关联。那我想单据编号应该是主表的主键,子表的外键吧。
目前,可以肯定的是,在主表记录中,单据编号的唯一性。(一般这样的字段都是主键吧)。
子表中的主表id的字段,必须与单据编号一致。否则数据就是错误的了。
还以用友的为例,似乎在增加一个新单据时,已经生成了一个单据号,但是如果取消操作,这个单据号应该不保存,下次还应该再出现。但是,如果已保存的单据被删掉后,该号将不能再次使用。
那么,实现这个结果,这个单据编号是如何设计的?以什么方式得到的?可以既保证连续性,又保证了唯一性。同时,即使在并发的状态下,也应该不断号。比如,多人同时增加单据,先增加的后来取消操作了,但是保存的单据的单据号不应该中间有空号。
问题5:==在sql server中 如何显示的表示在事务的执行中加锁,解锁。及控制锁粒度。
问题6:==同问题5,只是是在c#,程序中如何表示?
问题7:==注意到相关的锁大多指的update的例子。那么insert呢?需要加锁吗?因为我之前有个不太好的设计,两个表,也是b表以a表的主键为外键。a表的主键是自增id。我原来的思路是插入记录到a,然后获取@@identity值。将此值作为字段值插入b。插入a b的数据是同一页面录入的,但是后来一想到,如果有并发,在插入a后 又有其他人也插入一条到a,那么不是取出的@@identity值就不对了?所以有此问。
问题8:guid 看书上说几乎不会重复,那么,还是有重复的可能,是不是就不适合做主键?那么用来作什么呢?
权限只能有一百分。
27 个解决方案
#1
1、不需要自己做控件。可以用DataTable.Update()方法。可以多笔修改或添加的资料同步到数据库。
2、DataTable.Update()
后面的留给大哥们
2、DataTable.Update()
后面的留给大哥们
#2
帮顶,我也想知道
#3
1.me用的是循环
2.me一般是delete 符合条件的,在insert
3.i donot know
4.相当难,但是一定会有人做出来的,慢慢研究
5.不太明白
6.也很想知道
7.也很想知道
8.确实不太适合,倒不是因为重复与否(估计16位有字符,还有数字的重复的几率,真是比中彩票难上几万倍),而是因为guid他不能排序。guid不可能重复是有依据的注册表内的那些安装软件,从来都没有重复的
2.me一般是delete 符合条件的,在insert
3.i donot know
4.相当难,但是一定会有人做出来的,慢慢研究
5.不太明白
6.也很想知道
7.也很想知道
8.确实不太适合,倒不是因为重复与否(估计16位有字符,还有数字的重复的几率,真是比中彩票难上几万倍),而是因为guid他不能排序。guid不可能重复是有依据的注册表内的那些安装软件,从来都没有重复的
#4
1:可以使用GridView等数据控件的动态添加行,一次性批量录入。
2:批量和楼上差不多,你可以用CheckBox来选定,然后在来进行修改。
3:很多人同时录入一次能批量多少呢?我的库一次批量1W+的数据,也没感觉有什么问题。
4:表之间的关系我个人认为是自己确定的,也没有说一定要一样,当然要遵循规则,最好一直。
编号基本像单据这样基本是自定意流水号,而不是直接用主键,基本就是在插入之前先获得上次插入的最大号,然后+1。推荐用存储过程或者触发器完成,当然用程序也可以。
5,6,7,8有没有用过,有太含糊的,不答了。
2:批量和楼上差不多,你可以用CheckBox来选定,然后在来进行修改。
3:很多人同时录入一次能批量多少呢?我的库一次批量1W+的数据,也没感觉有什么问题。
4:表之间的关系我个人认为是自己确定的,也没有说一定要一样,当然要遵循规则,最好一直。
编号基本像单据这样基本是自定意流水号,而不是直接用主键,基本就是在插入之前先获得上次插入的最大号,然后+1。推荐用存储过程或者触发器完成,当然用程序也可以。
5,6,7,8有没有用过,有太含糊的,不答了。
#5
ERP不是胡搞辖搞得
#6
还没有做过...
#7
问题1 事务...
问题2 事务...
问题3 事务...
问题4 全局单号编码器...自己写...
可以既保证连续性,又保证了唯一性。同时,即使在并发的状态下,也应该不断号。比如,多人同时增加单据,先增加的后来取消操作了,但是保存的单据的单据号不应该中间有空号。
----------------------------
为什么要保证连续性?为什么不应该中间有空号?
问题5、6:看文档吧...
问题7:事务...
问题8:"有重复的可能"只是理论上的,基本上它只适合用来做主键,通常用于分布式系统...
问题2 事务...
问题3 事务...
问题4 全局单号编码器...自己写...
可以既保证连续性,又保证了唯一性。同时,即使在并发的状态下,也应该不断号。比如,多人同时增加单据,先增加的后来取消操作了,但是保存的单据的单据号不应该中间有空号。
----------------------------
为什么要保证连续性?为什么不应该中间有空号?
问题5、6:看文档吧...
问题7:事务...
问题8:"有重复的可能"只是理论上的,基本上它只适合用来做主键,通常用于分布式系统...
#8
ERP是什么?我是菜鸟
#9
回复人:vrhero(专业路过/有一天我躺下来/从此不再结帖...)
------------------------------------------
你真的不知道为什么不应该有断号吗?那问问客户的实际需求吧,再看看手工单据吧。
回复人:Dg_web() ( 一级(初级)) 信誉:100 2007-06-18 15:22:00 得分:0
?
ERP不是胡搞辖搞得
==========================================
啥意思,有人看的懂这位高人的话吗?
------------------------------------------
你真的不知道为什么不应该有断号吗?那问问客户的实际需求吧,再看看手工单据吧。
回复人:Dg_web() ( 一级(初级)) 信誉:100 2007-06-18 15:22:00 得分:0
?
ERP不是胡搞辖搞得
==========================================
啥意思,有人看的懂这位高人的话吗?
#10
你真的不知道为什么不应该有断号吗?那问问客户的实际需求吧,再看看手工单据吧。
-----------------------
客户需求不是他们说什么就是什么,ERP不是为了满足客户现有需求,而是为了改进其现有需求...
至于手工单据...
1.写错了的单会怎样?继续使用它的单号?你见过吗?
2.如果ERP只是为了取代手工单据,上个进销存好了...
ERP不是编程,不是软件,不是技术...
-----------------------
客户需求不是他们说什么就是什么,ERP不是为了满足客户现有需求,而是为了改进其现有需求...
至于手工单据...
1.写错了的单会怎样?继续使用它的单号?你见过吗?
2.如果ERP只是为了取代手工单据,上个进销存好了...
ERP不是编程,不是软件,不是技术...
#11
本来你的问题都跟asp.net无关,不是很想仔细回答,仅仅算作提示吧:
Q: 问题1 == 库存期初数据的录入。
一般情况下,录入与修改已录过的数据在操作上是同时的。拿我用过的用友的产品为例。
点击菜单的修改按钮后,可以实际开始操作。在一个二维表格中,按行录入数据。点击保存后,这些记录将在验证后插入数据库。
但是,我们是不知道每次会录入多少条的。我用sqlcommand每次只能插入一条。所以,不知大家是用的什么来做,需要作自定义控件吗?
A: 有两种可能性。
一种,是临时单据根本不保存在数据库中,而是在ViewState中,你设计关于关于单据和单据明细的class,将对象实例保存在ViewState。这样做的好处是一旦用户离开录入页面,整个单据页就扔掉了。
另外一种,是将临时订单保存在数据库中,并且你要记录最后修改时间(页面处理时间)。然后程序定期删除较长时间没有修改的订单就可以了(例如在application_start中清理超过72小时没有修改过的订单)。其实这些数据不删除也不影响。当用户确定订单的时候,把数据从临时订单表移到正式订单表。这个设计的好处是可以跟前一个相对。
设计web应用不能想当然地照搬c/s程序的说法。如果你写过web程序,仔细想一下程序是怎么跟数据库通讯的就会发现,交互式的asp.net程序再这个过程中无法使用数据库事务。即使对于c/s程序设计,基本的概念,数据库事务应该处理那些在几秒钟内迅速完成的事务,不是简单随便套用在长事务上的。
Q: 问题2
A: 与问题1一样。
Q: 问题3:==问题1 和问题2在 较多人并发的状态下如何做呢??因为一般会很多人为了赶进度同时录入的。
A: 如果多人编辑同一个单据的明细部分(例如明细部分实在太长),那么采用上述第二种。但是这在实际管理中可能应该是不允许的,跟客户沟通一下。如果你可以不这样设计,就不要这样设计。如果可以不这样设计,那么上述第一种也可以。还是一样地理由,这不考虑使用数据库事务。即使不是web应用程序,即使是c/s程序,也不能让一个人锁住一堆记录然后去上厕所或者睡大觉同时别人无法访问这些数据。事务只有当一条明细记录存入数据库并且可能同时更新多条记录这个瞬间操作时才使用,而不是在一个人逐一录入多条记录的长事务中使用。长事务是业务逻辑,不是数据库事务。搞数据库比较差的人会犯这个想当然的错误。
Q: 问题4==录入业务单据的时候,......似乎在增加一个新单据时,已经生成了一个单据号,但是如果取消操作,这个单据号应该不保存,下次还应该再出现。但是,如果已保存的单据被删掉后,该号将不能再次使用。......
那么,实现这个结果,这个单据编号是如何设计的?以什么方式得到的?可以既保证连续
A: 在录入时显示的单据号只是一个临时编号,在单据确认录入完成时单据号需要重新更新。
Q: 问题5:==在sql server中 如何显示的表示在事务的执行中加锁,解锁。及控制锁粒度。
A: 事务,不要搞什么“加锁、解锁”的。这个术语用于理解事务的部分机制,不需要你去编写。过去的特别低级的pc机小型“数据库”系统,例如foxpro、cliper,以及少数专给业余编程人员使用的“大型”数据库,不支持事务。正规的数据库系统都支持事务,甚至Jet(Access数据库引擎)早在10年前就已经支持。
Q: 问题6:==同问题5,只是是在c#,程序中如何表示?
A: 在ado.net中,事务使用 DbConnection.BeginTransaction 方法启动,是用 Transaction.Commit 和 .Rollback 两个方法提交或者回滚。自己查一下资料。
另外我要说一下,.net是一个很丰富、很宽广的开发平台。不论c#、vb.net、JScript.net、C# Builder、Eiffel.Net等任何编程语言,都是一样的。语言只是一种体验,只是语法稍有不同,但是他们针对的系统的设计和操作完全一样。你应该去理解服务系统(例如ado.net)如何使用,而不是语言如何使用。
Q: 问题7:==注意到相关的锁大多指的update的例子。那么insert呢?需要加锁吗?因为我之前有个不太好的设计,两个表,也是b表以a表的主键为外键。a表的主键是自增id。我原来的思路是插入记录到a,然后获取@@identity值。将此值作为字段值插入b。插入a b的数据是同一页面录入的,但是后来一想到,如果有并发,在插入a后 又有其他人也插入一条到a,那么不是取出的@@identity值就不对了?所以有此问。
A: 这是两个问题。
所有对数据库的修改都要考虑在事务之内。
业务流水号跟 int identity 值没有关系。这个值只是数据库用于保证表内的主键唯一(实际上只要一条命令就能命令数据库重新从一个比较小的数值开始,并不保证数值总是递增的),但是你的业务要求连续的流水号,应该自己编写程序来存入流水号,不要使用数据库的值。
Q: 问题8:guid 看书上说几乎不会重复,那么,还是有重复的可能,是不是就不适合做主键?那么用来作什么呢?
A:我记得文献记载,理论上,只要你是使用.net的 Guid.NewGuid() 产生的编号,几百亿年内基本可以保证不会重复。
但是我还是要说明,这个编号能够保证当你把数据复制到其它任何数据库里都不会重复,例如你的程序收集各个分公司的订单到总的订单档案库中,仍然不会搞混。但是这并不能代替业务流水号,流水号也不能代替它。它如果用于记录的主键,是这个技术意义上的作用,同时你仍然需要另外一个字段作为业务流水号。凡是有业务意义的字段,迟早都有可能需要更改。例如个人的身份证号有可能需要更改,因此业务意义的所谓“唯一”的编号不应作为代表数据的主键,使用无业务意义的主键比较通用。
Q: 问题1 == 库存期初数据的录入。
一般情况下,录入与修改已录过的数据在操作上是同时的。拿我用过的用友的产品为例。
点击菜单的修改按钮后,可以实际开始操作。在一个二维表格中,按行录入数据。点击保存后,这些记录将在验证后插入数据库。
但是,我们是不知道每次会录入多少条的。我用sqlcommand每次只能插入一条。所以,不知大家是用的什么来做,需要作自定义控件吗?
A: 有两种可能性。
一种,是临时单据根本不保存在数据库中,而是在ViewState中,你设计关于关于单据和单据明细的class,将对象实例保存在ViewState。这样做的好处是一旦用户离开录入页面,整个单据页就扔掉了。
另外一种,是将临时订单保存在数据库中,并且你要记录最后修改时间(页面处理时间)。然后程序定期删除较长时间没有修改的订单就可以了(例如在application_start中清理超过72小时没有修改过的订单)。其实这些数据不删除也不影响。当用户确定订单的时候,把数据从临时订单表移到正式订单表。这个设计的好处是可以跟前一个相对。
设计web应用不能想当然地照搬c/s程序的说法。如果你写过web程序,仔细想一下程序是怎么跟数据库通讯的就会发现,交互式的asp.net程序再这个过程中无法使用数据库事务。即使对于c/s程序设计,基本的概念,数据库事务应该处理那些在几秒钟内迅速完成的事务,不是简单随便套用在长事务上的。
Q: 问题2
A: 与问题1一样。
Q: 问题3:==问题1 和问题2在 较多人并发的状态下如何做呢??因为一般会很多人为了赶进度同时录入的。
A: 如果多人编辑同一个单据的明细部分(例如明细部分实在太长),那么采用上述第二种。但是这在实际管理中可能应该是不允许的,跟客户沟通一下。如果你可以不这样设计,就不要这样设计。如果可以不这样设计,那么上述第一种也可以。还是一样地理由,这不考虑使用数据库事务。即使不是web应用程序,即使是c/s程序,也不能让一个人锁住一堆记录然后去上厕所或者睡大觉同时别人无法访问这些数据。事务只有当一条明细记录存入数据库并且可能同时更新多条记录这个瞬间操作时才使用,而不是在一个人逐一录入多条记录的长事务中使用。长事务是业务逻辑,不是数据库事务。搞数据库比较差的人会犯这个想当然的错误。
Q: 问题4==录入业务单据的时候,......似乎在增加一个新单据时,已经生成了一个单据号,但是如果取消操作,这个单据号应该不保存,下次还应该再出现。但是,如果已保存的单据被删掉后,该号将不能再次使用。......
那么,实现这个结果,这个单据编号是如何设计的?以什么方式得到的?可以既保证连续
A: 在录入时显示的单据号只是一个临时编号,在单据确认录入完成时单据号需要重新更新。
Q: 问题5:==在sql server中 如何显示的表示在事务的执行中加锁,解锁。及控制锁粒度。
A: 事务,不要搞什么“加锁、解锁”的。这个术语用于理解事务的部分机制,不需要你去编写。过去的特别低级的pc机小型“数据库”系统,例如foxpro、cliper,以及少数专给业余编程人员使用的“大型”数据库,不支持事务。正规的数据库系统都支持事务,甚至Jet(Access数据库引擎)早在10年前就已经支持。
Q: 问题6:==同问题5,只是是在c#,程序中如何表示?
A: 在ado.net中,事务使用 DbConnection.BeginTransaction 方法启动,是用 Transaction.Commit 和 .Rollback 两个方法提交或者回滚。自己查一下资料。
另外我要说一下,.net是一个很丰富、很宽广的开发平台。不论c#、vb.net、JScript.net、C# Builder、Eiffel.Net等任何编程语言,都是一样的。语言只是一种体验,只是语法稍有不同,但是他们针对的系统的设计和操作完全一样。你应该去理解服务系统(例如ado.net)如何使用,而不是语言如何使用。
Q: 问题7:==注意到相关的锁大多指的update的例子。那么insert呢?需要加锁吗?因为我之前有个不太好的设计,两个表,也是b表以a表的主键为外键。a表的主键是自增id。我原来的思路是插入记录到a,然后获取@@identity值。将此值作为字段值插入b。插入a b的数据是同一页面录入的,但是后来一想到,如果有并发,在插入a后 又有其他人也插入一条到a,那么不是取出的@@identity值就不对了?所以有此问。
A: 这是两个问题。
所有对数据库的修改都要考虑在事务之内。
业务流水号跟 int identity 值没有关系。这个值只是数据库用于保证表内的主键唯一(实际上只要一条命令就能命令数据库重新从一个比较小的数值开始,并不保证数值总是递增的),但是你的业务要求连续的流水号,应该自己编写程序来存入流水号,不要使用数据库的值。
Q: 问题8:guid 看书上说几乎不会重复,那么,还是有重复的可能,是不是就不适合做主键?那么用来作什么呢?
A:我记得文献记载,理论上,只要你是使用.net的 Guid.NewGuid() 产生的编号,几百亿年内基本可以保证不会重复。
但是我还是要说明,这个编号能够保证当你把数据复制到其它任何数据库里都不会重复,例如你的程序收集各个分公司的订单到总的订单档案库中,仍然不会搞混。但是这并不能代替业务流水号,流水号也不能代替它。它如果用于记录的主键,是这个技术意义上的作用,同时你仍然需要另外一个字段作为业务流水号。凡是有业务意义的字段,迟早都有可能需要更改。例如个人的身份证号有可能需要更改,因此业务意义的所谓“唯一”的编号不应作为代表数据的主键,使用无业务意义的主键比较通用。
#12
看看数据库原理中事务的理论,再根据界面上控制
#13
如果订单号不连续的现象太频繁,用户就会耻笑,就会怀疑设计人员的能力和是否尽力,这个理由足够你花力气好好处理流水号问题。技术的理由(程序员是否觉得方便)不能代替业务需求。
#14
如果用户要求你开发一个小功能,删除某一个订单号然后将后边的所有订单(如果订单号按年份和订单类型来分组编写那么其实就只需要改变很少的记录)重新编号,你就应该开发这个小功能。
业务编号不要作为数据库主键。
业务编号不要作为数据库主键。
#15
另外,如果电脑只是原样照抄手工单据,那么单据号应该以手工录入为准,而不是由电脑编号的。你说过“多人录入”之类的问题。你要在设计之前搞清楚,到底人工拿着原始票据(例如一个订单有合同、多种发票、发货票、验收入库单等等很多原始票据)然后在电脑上编写记帐单据,还是人工编写好记帐单据然后只是照抄。你应该做好系统分析,编程知识一种辅助技能,开发管理系统需要首先懂业务。
#16
回复人:vrhero(专业路过/有一天我躺下来/从此不再结帖...) (
在开发上,我确实是个新手。但我的专业和三年多的ERP的实施经验,在对ERP的理解上,判断客户需求是否合理上还是有一定自信的。
对于你的说法,本来是想一一反驳一下的,因为那种说法几乎只是哗众那种取宠而已。不过感觉没必要了,与我这个帖子讨论的无关。
我探讨的是技术问题,我关心的是首要是并发下 旧数据的修改 新数据的存储问题如何做。然后是其他的更深的扩展应用能否实现如何实现。
算了,不打口水仗了,没有意义。您要是会但不愿意帮忙解决,那也没什么好说的。
在开发上,我确实是个新手。但我的专业和三年多的ERP的实施经验,在对ERP的理解上,判断客户需求是否合理上还是有一定自信的。
对于你的说法,本来是想一一反驳一下的,因为那种说法几乎只是哗众那种取宠而已。不过感觉没必要了,与我这个帖子讨论的无关。
我探讨的是技术问题,我关心的是首要是并发下 旧数据的修改 新数据的存储问题如何做。然后是其他的更深的扩展应用能否实现如何实现。
算了,不打口水仗了,没有意义。您要是会但不愿意帮忙解决,那也没什么好说的。
#17
非常感谢sp1234
首先说明确实不适合在asp.net中,因为除了问题7中的例子是我实际在编一个asp.net程序时碰到的实际情况,由此引发了其他所有我对于并发状态下的问题的考虑。其他的例子是结合我对其他产品如用友的了解而提的,确实应算作winform 只是没发现winform区。
我想,目前产生这些问题的核心是,不知道该怎么用。可确实看了许多资料了,都写的迷迷糊糊的。也无法验证,因为根本就看不出状态的变化,更别提有环境去测试执行结果了。
比如,书上,都会讲事务 锁 锁粒度 *协议等等。
但是,我不知道当我执行一条select 语句时,是否是上锁了,那种类型的锁。锁的是表 还是记录 还是数据库。这些都看不出来,也不知道如果我想对一个表上共享锁的话,该如何写。
还是在执行sql语句时,根据语句是select 还是insert 还是update 还是delete 。系统会自动根据语句来进行锁定。
所以 没有基本的应用 更无法提高了。
首先说明确实不适合在asp.net中,因为除了问题7中的例子是我实际在编一个asp.net程序时碰到的实际情况,由此引发了其他所有我对于并发状态下的问题的考虑。其他的例子是结合我对其他产品如用友的了解而提的,确实应算作winform 只是没发现winform区。
我想,目前产生这些问题的核心是,不知道该怎么用。可确实看了许多资料了,都写的迷迷糊糊的。也无法验证,因为根本就看不出状态的变化,更别提有环境去测试执行结果了。
比如,书上,都会讲事务 锁 锁粒度 *协议等等。
但是,我不知道当我执行一条select 语句时,是否是上锁了,那种类型的锁。锁的是表 还是记录 还是数据库。这些都看不出来,也不知道如果我想对一个表上共享锁的话,该如何写。
还是在执行sql语句时,根据语句是select 还是insert 还是update 还是delete 。系统会自动根据语句来进行锁定。
所以 没有基本的应用 更无法提高了。
#18
对了 问题3这种情况在我看来是绝对合理并且多次遇到的,我仅仅是就操作来讲。
因为许多客户的期初的数据量太大,而且,基本都是手工数据。初始化时基本上都只能靠手工录入。
可为了赶进度,经常是许多人同时录入,每人录入一部分。那么多人就会同时操作一个节点。操作中也不都是录入新数据。录一部分,会检查一下,错误的会修改掉。
别的产品我不知道,用友的库存期初,在录入 修改 查询是一个界面。当然别的地方也有报表可以查。
因为许多客户的期初的数据量太大,而且,基本都是手工数据。初始化时基本上都只能靠手工录入。
可为了赶进度,经常是许多人同时录入,每人录入一部分。那么多人就会同时操作一个节点。操作中也不都是录入新数据。录一部分,会检查一下,错误的会修改掉。
别的产品我不知道,用友的库存期初,在录入 修改 查询是一个界面。当然别的地方也有报表可以查。
#19
不太懂
帮你顶
帮你顶
#20
问题太多了,没读过这么长的文章,但用友的单据主子表不是通过单据号关联的,是通过id这一列关联的
#21
我靠,多好的学习机会
#22
还有每添加完一张单据后,系统就把单据号存储到一个表中,下次添加时再读取该表,而删除时就没这些操作,所以删除完会断号
#23
UP
#24
回复人:iamdazuiniao() ( 一级(初级)) 信誉:100
我让人帮我查了下u8的数据字典,确实,销售发票主表
Column Name Description Datatype Length Allow Nulls
SBVID 销售发票主表标识 int 4 False
cSBVCode 销售发票号 varchar 30 True
子表
SBVID 销售发票主表标识 int 4 False
AutoID 销售发票子表标识 int 4 False
所以,更疑惑了。我想主表标识应该是identity(1,1)的吧,那是不是意味着和我问题3的方式有点类似,插入主表,然后得到id,然后将id与明细信息插入子表?
我让人帮我查了下u8的数据字典,确实,销售发票主表
Column Name Description Datatype Length Allow Nulls
SBVID 销售发票主表标识 int 4 False
cSBVCode 销售发票号 varchar 30 True
子表
SBVID 销售发票主表标识 int 4 False
AutoID 销售发票子表标识 int 4 False
所以,更疑惑了。我想主表标识应该是identity(1,1)的吧,那是不是意味着和我问题3的方式有点类似,插入主表,然后得到id,然后将id与明细信息插入子表?
#25
up
#26
应该是这样,先得到主表最大id,插入主表信息,再得到子表autoid,连同主表id和子表信息一同插入子表,这些是我自己的观点,不一定对。至于并发什么的我也不懂,我只会用简单的事务。
#27
说得好!
#1
1、不需要自己做控件。可以用DataTable.Update()方法。可以多笔修改或添加的资料同步到数据库。
2、DataTable.Update()
后面的留给大哥们
2、DataTable.Update()
后面的留给大哥们
#2
帮顶,我也想知道
#3
1.me用的是循环
2.me一般是delete 符合条件的,在insert
3.i donot know
4.相当难,但是一定会有人做出来的,慢慢研究
5.不太明白
6.也很想知道
7.也很想知道
8.确实不太适合,倒不是因为重复与否(估计16位有字符,还有数字的重复的几率,真是比中彩票难上几万倍),而是因为guid他不能排序。guid不可能重复是有依据的注册表内的那些安装软件,从来都没有重复的
2.me一般是delete 符合条件的,在insert
3.i donot know
4.相当难,但是一定会有人做出来的,慢慢研究
5.不太明白
6.也很想知道
7.也很想知道
8.确实不太适合,倒不是因为重复与否(估计16位有字符,还有数字的重复的几率,真是比中彩票难上几万倍),而是因为guid他不能排序。guid不可能重复是有依据的注册表内的那些安装软件,从来都没有重复的
#4
1:可以使用GridView等数据控件的动态添加行,一次性批量录入。
2:批量和楼上差不多,你可以用CheckBox来选定,然后在来进行修改。
3:很多人同时录入一次能批量多少呢?我的库一次批量1W+的数据,也没感觉有什么问题。
4:表之间的关系我个人认为是自己确定的,也没有说一定要一样,当然要遵循规则,最好一直。
编号基本像单据这样基本是自定意流水号,而不是直接用主键,基本就是在插入之前先获得上次插入的最大号,然后+1。推荐用存储过程或者触发器完成,当然用程序也可以。
5,6,7,8有没有用过,有太含糊的,不答了。
2:批量和楼上差不多,你可以用CheckBox来选定,然后在来进行修改。
3:很多人同时录入一次能批量多少呢?我的库一次批量1W+的数据,也没感觉有什么问题。
4:表之间的关系我个人认为是自己确定的,也没有说一定要一样,当然要遵循规则,最好一直。
编号基本像单据这样基本是自定意流水号,而不是直接用主键,基本就是在插入之前先获得上次插入的最大号,然后+1。推荐用存储过程或者触发器完成,当然用程序也可以。
5,6,7,8有没有用过,有太含糊的,不答了。
#5
ERP不是胡搞辖搞得
#6
还没有做过...
#7
问题1 事务...
问题2 事务...
问题3 事务...
问题4 全局单号编码器...自己写...
可以既保证连续性,又保证了唯一性。同时,即使在并发的状态下,也应该不断号。比如,多人同时增加单据,先增加的后来取消操作了,但是保存的单据的单据号不应该中间有空号。
----------------------------
为什么要保证连续性?为什么不应该中间有空号?
问题5、6:看文档吧...
问题7:事务...
问题8:"有重复的可能"只是理论上的,基本上它只适合用来做主键,通常用于分布式系统...
问题2 事务...
问题3 事务...
问题4 全局单号编码器...自己写...
可以既保证连续性,又保证了唯一性。同时,即使在并发的状态下,也应该不断号。比如,多人同时增加单据,先增加的后来取消操作了,但是保存的单据的单据号不应该中间有空号。
----------------------------
为什么要保证连续性?为什么不应该中间有空号?
问题5、6:看文档吧...
问题7:事务...
问题8:"有重复的可能"只是理论上的,基本上它只适合用来做主键,通常用于分布式系统...
#8
ERP是什么?我是菜鸟
#9
回复人:vrhero(专业路过/有一天我躺下来/从此不再结帖...)
------------------------------------------
你真的不知道为什么不应该有断号吗?那问问客户的实际需求吧,再看看手工单据吧。
回复人:Dg_web() ( 一级(初级)) 信誉:100 2007-06-18 15:22:00 得分:0
?
ERP不是胡搞辖搞得
==========================================
啥意思,有人看的懂这位高人的话吗?
------------------------------------------
你真的不知道为什么不应该有断号吗?那问问客户的实际需求吧,再看看手工单据吧。
回复人:Dg_web() ( 一级(初级)) 信誉:100 2007-06-18 15:22:00 得分:0
?
ERP不是胡搞辖搞得
==========================================
啥意思,有人看的懂这位高人的话吗?
#10
你真的不知道为什么不应该有断号吗?那问问客户的实际需求吧,再看看手工单据吧。
-----------------------
客户需求不是他们说什么就是什么,ERP不是为了满足客户现有需求,而是为了改进其现有需求...
至于手工单据...
1.写错了的单会怎样?继续使用它的单号?你见过吗?
2.如果ERP只是为了取代手工单据,上个进销存好了...
ERP不是编程,不是软件,不是技术...
-----------------------
客户需求不是他们说什么就是什么,ERP不是为了满足客户现有需求,而是为了改进其现有需求...
至于手工单据...
1.写错了的单会怎样?继续使用它的单号?你见过吗?
2.如果ERP只是为了取代手工单据,上个进销存好了...
ERP不是编程,不是软件,不是技术...
#11
本来你的问题都跟asp.net无关,不是很想仔细回答,仅仅算作提示吧:
Q: 问题1 == 库存期初数据的录入。
一般情况下,录入与修改已录过的数据在操作上是同时的。拿我用过的用友的产品为例。
点击菜单的修改按钮后,可以实际开始操作。在一个二维表格中,按行录入数据。点击保存后,这些记录将在验证后插入数据库。
但是,我们是不知道每次会录入多少条的。我用sqlcommand每次只能插入一条。所以,不知大家是用的什么来做,需要作自定义控件吗?
A: 有两种可能性。
一种,是临时单据根本不保存在数据库中,而是在ViewState中,你设计关于关于单据和单据明细的class,将对象实例保存在ViewState。这样做的好处是一旦用户离开录入页面,整个单据页就扔掉了。
另外一种,是将临时订单保存在数据库中,并且你要记录最后修改时间(页面处理时间)。然后程序定期删除较长时间没有修改的订单就可以了(例如在application_start中清理超过72小时没有修改过的订单)。其实这些数据不删除也不影响。当用户确定订单的时候,把数据从临时订单表移到正式订单表。这个设计的好处是可以跟前一个相对。
设计web应用不能想当然地照搬c/s程序的说法。如果你写过web程序,仔细想一下程序是怎么跟数据库通讯的就会发现,交互式的asp.net程序再这个过程中无法使用数据库事务。即使对于c/s程序设计,基本的概念,数据库事务应该处理那些在几秒钟内迅速完成的事务,不是简单随便套用在长事务上的。
Q: 问题2
A: 与问题1一样。
Q: 问题3:==问题1 和问题2在 较多人并发的状态下如何做呢??因为一般会很多人为了赶进度同时录入的。
A: 如果多人编辑同一个单据的明细部分(例如明细部分实在太长),那么采用上述第二种。但是这在实际管理中可能应该是不允许的,跟客户沟通一下。如果你可以不这样设计,就不要这样设计。如果可以不这样设计,那么上述第一种也可以。还是一样地理由,这不考虑使用数据库事务。即使不是web应用程序,即使是c/s程序,也不能让一个人锁住一堆记录然后去上厕所或者睡大觉同时别人无法访问这些数据。事务只有当一条明细记录存入数据库并且可能同时更新多条记录这个瞬间操作时才使用,而不是在一个人逐一录入多条记录的长事务中使用。长事务是业务逻辑,不是数据库事务。搞数据库比较差的人会犯这个想当然的错误。
Q: 问题4==录入业务单据的时候,......似乎在增加一个新单据时,已经生成了一个单据号,但是如果取消操作,这个单据号应该不保存,下次还应该再出现。但是,如果已保存的单据被删掉后,该号将不能再次使用。......
那么,实现这个结果,这个单据编号是如何设计的?以什么方式得到的?可以既保证连续
A: 在录入时显示的单据号只是一个临时编号,在单据确认录入完成时单据号需要重新更新。
Q: 问题5:==在sql server中 如何显示的表示在事务的执行中加锁,解锁。及控制锁粒度。
A: 事务,不要搞什么“加锁、解锁”的。这个术语用于理解事务的部分机制,不需要你去编写。过去的特别低级的pc机小型“数据库”系统,例如foxpro、cliper,以及少数专给业余编程人员使用的“大型”数据库,不支持事务。正规的数据库系统都支持事务,甚至Jet(Access数据库引擎)早在10年前就已经支持。
Q: 问题6:==同问题5,只是是在c#,程序中如何表示?
A: 在ado.net中,事务使用 DbConnection.BeginTransaction 方法启动,是用 Transaction.Commit 和 .Rollback 两个方法提交或者回滚。自己查一下资料。
另外我要说一下,.net是一个很丰富、很宽广的开发平台。不论c#、vb.net、JScript.net、C# Builder、Eiffel.Net等任何编程语言,都是一样的。语言只是一种体验,只是语法稍有不同,但是他们针对的系统的设计和操作完全一样。你应该去理解服务系统(例如ado.net)如何使用,而不是语言如何使用。
Q: 问题7:==注意到相关的锁大多指的update的例子。那么insert呢?需要加锁吗?因为我之前有个不太好的设计,两个表,也是b表以a表的主键为外键。a表的主键是自增id。我原来的思路是插入记录到a,然后获取@@identity值。将此值作为字段值插入b。插入a b的数据是同一页面录入的,但是后来一想到,如果有并发,在插入a后 又有其他人也插入一条到a,那么不是取出的@@identity值就不对了?所以有此问。
A: 这是两个问题。
所有对数据库的修改都要考虑在事务之内。
业务流水号跟 int identity 值没有关系。这个值只是数据库用于保证表内的主键唯一(实际上只要一条命令就能命令数据库重新从一个比较小的数值开始,并不保证数值总是递增的),但是你的业务要求连续的流水号,应该自己编写程序来存入流水号,不要使用数据库的值。
Q: 问题8:guid 看书上说几乎不会重复,那么,还是有重复的可能,是不是就不适合做主键?那么用来作什么呢?
A:我记得文献记载,理论上,只要你是使用.net的 Guid.NewGuid() 产生的编号,几百亿年内基本可以保证不会重复。
但是我还是要说明,这个编号能够保证当你把数据复制到其它任何数据库里都不会重复,例如你的程序收集各个分公司的订单到总的订单档案库中,仍然不会搞混。但是这并不能代替业务流水号,流水号也不能代替它。它如果用于记录的主键,是这个技术意义上的作用,同时你仍然需要另外一个字段作为业务流水号。凡是有业务意义的字段,迟早都有可能需要更改。例如个人的身份证号有可能需要更改,因此业务意义的所谓“唯一”的编号不应作为代表数据的主键,使用无业务意义的主键比较通用。
Q: 问题1 == 库存期初数据的录入。
一般情况下,录入与修改已录过的数据在操作上是同时的。拿我用过的用友的产品为例。
点击菜单的修改按钮后,可以实际开始操作。在一个二维表格中,按行录入数据。点击保存后,这些记录将在验证后插入数据库。
但是,我们是不知道每次会录入多少条的。我用sqlcommand每次只能插入一条。所以,不知大家是用的什么来做,需要作自定义控件吗?
A: 有两种可能性。
一种,是临时单据根本不保存在数据库中,而是在ViewState中,你设计关于关于单据和单据明细的class,将对象实例保存在ViewState。这样做的好处是一旦用户离开录入页面,整个单据页就扔掉了。
另外一种,是将临时订单保存在数据库中,并且你要记录最后修改时间(页面处理时间)。然后程序定期删除较长时间没有修改的订单就可以了(例如在application_start中清理超过72小时没有修改过的订单)。其实这些数据不删除也不影响。当用户确定订单的时候,把数据从临时订单表移到正式订单表。这个设计的好处是可以跟前一个相对。
设计web应用不能想当然地照搬c/s程序的说法。如果你写过web程序,仔细想一下程序是怎么跟数据库通讯的就会发现,交互式的asp.net程序再这个过程中无法使用数据库事务。即使对于c/s程序设计,基本的概念,数据库事务应该处理那些在几秒钟内迅速完成的事务,不是简单随便套用在长事务上的。
Q: 问题2
A: 与问题1一样。
Q: 问题3:==问题1 和问题2在 较多人并发的状态下如何做呢??因为一般会很多人为了赶进度同时录入的。
A: 如果多人编辑同一个单据的明细部分(例如明细部分实在太长),那么采用上述第二种。但是这在实际管理中可能应该是不允许的,跟客户沟通一下。如果你可以不这样设计,就不要这样设计。如果可以不这样设计,那么上述第一种也可以。还是一样地理由,这不考虑使用数据库事务。即使不是web应用程序,即使是c/s程序,也不能让一个人锁住一堆记录然后去上厕所或者睡大觉同时别人无法访问这些数据。事务只有当一条明细记录存入数据库并且可能同时更新多条记录这个瞬间操作时才使用,而不是在一个人逐一录入多条记录的长事务中使用。长事务是业务逻辑,不是数据库事务。搞数据库比较差的人会犯这个想当然的错误。
Q: 问题4==录入业务单据的时候,......似乎在增加一个新单据时,已经生成了一个单据号,但是如果取消操作,这个单据号应该不保存,下次还应该再出现。但是,如果已保存的单据被删掉后,该号将不能再次使用。......
那么,实现这个结果,这个单据编号是如何设计的?以什么方式得到的?可以既保证连续
A: 在录入时显示的单据号只是一个临时编号,在单据确认录入完成时单据号需要重新更新。
Q: 问题5:==在sql server中 如何显示的表示在事务的执行中加锁,解锁。及控制锁粒度。
A: 事务,不要搞什么“加锁、解锁”的。这个术语用于理解事务的部分机制,不需要你去编写。过去的特别低级的pc机小型“数据库”系统,例如foxpro、cliper,以及少数专给业余编程人员使用的“大型”数据库,不支持事务。正规的数据库系统都支持事务,甚至Jet(Access数据库引擎)早在10年前就已经支持。
Q: 问题6:==同问题5,只是是在c#,程序中如何表示?
A: 在ado.net中,事务使用 DbConnection.BeginTransaction 方法启动,是用 Transaction.Commit 和 .Rollback 两个方法提交或者回滚。自己查一下资料。
另外我要说一下,.net是一个很丰富、很宽广的开发平台。不论c#、vb.net、JScript.net、C# Builder、Eiffel.Net等任何编程语言,都是一样的。语言只是一种体验,只是语法稍有不同,但是他们针对的系统的设计和操作完全一样。你应该去理解服务系统(例如ado.net)如何使用,而不是语言如何使用。
Q: 问题7:==注意到相关的锁大多指的update的例子。那么insert呢?需要加锁吗?因为我之前有个不太好的设计,两个表,也是b表以a表的主键为外键。a表的主键是自增id。我原来的思路是插入记录到a,然后获取@@identity值。将此值作为字段值插入b。插入a b的数据是同一页面录入的,但是后来一想到,如果有并发,在插入a后 又有其他人也插入一条到a,那么不是取出的@@identity值就不对了?所以有此问。
A: 这是两个问题。
所有对数据库的修改都要考虑在事务之内。
业务流水号跟 int identity 值没有关系。这个值只是数据库用于保证表内的主键唯一(实际上只要一条命令就能命令数据库重新从一个比较小的数值开始,并不保证数值总是递增的),但是你的业务要求连续的流水号,应该自己编写程序来存入流水号,不要使用数据库的值。
Q: 问题8:guid 看书上说几乎不会重复,那么,还是有重复的可能,是不是就不适合做主键?那么用来作什么呢?
A:我记得文献记载,理论上,只要你是使用.net的 Guid.NewGuid() 产生的编号,几百亿年内基本可以保证不会重复。
但是我还是要说明,这个编号能够保证当你把数据复制到其它任何数据库里都不会重复,例如你的程序收集各个分公司的订单到总的订单档案库中,仍然不会搞混。但是这并不能代替业务流水号,流水号也不能代替它。它如果用于记录的主键,是这个技术意义上的作用,同时你仍然需要另外一个字段作为业务流水号。凡是有业务意义的字段,迟早都有可能需要更改。例如个人的身份证号有可能需要更改,因此业务意义的所谓“唯一”的编号不应作为代表数据的主键,使用无业务意义的主键比较通用。
#12
看看数据库原理中事务的理论,再根据界面上控制
#13
如果订单号不连续的现象太频繁,用户就会耻笑,就会怀疑设计人员的能力和是否尽力,这个理由足够你花力气好好处理流水号问题。技术的理由(程序员是否觉得方便)不能代替业务需求。
#14
如果用户要求你开发一个小功能,删除某一个订单号然后将后边的所有订单(如果订单号按年份和订单类型来分组编写那么其实就只需要改变很少的记录)重新编号,你就应该开发这个小功能。
业务编号不要作为数据库主键。
业务编号不要作为数据库主键。
#15
另外,如果电脑只是原样照抄手工单据,那么单据号应该以手工录入为准,而不是由电脑编号的。你说过“多人录入”之类的问题。你要在设计之前搞清楚,到底人工拿着原始票据(例如一个订单有合同、多种发票、发货票、验收入库单等等很多原始票据)然后在电脑上编写记帐单据,还是人工编写好记帐单据然后只是照抄。你应该做好系统分析,编程知识一种辅助技能,开发管理系统需要首先懂业务。
#16
回复人:vrhero(专业路过/有一天我躺下来/从此不再结帖...) (
在开发上,我确实是个新手。但我的专业和三年多的ERP的实施经验,在对ERP的理解上,判断客户需求是否合理上还是有一定自信的。
对于你的说法,本来是想一一反驳一下的,因为那种说法几乎只是哗众那种取宠而已。不过感觉没必要了,与我这个帖子讨论的无关。
我探讨的是技术问题,我关心的是首要是并发下 旧数据的修改 新数据的存储问题如何做。然后是其他的更深的扩展应用能否实现如何实现。
算了,不打口水仗了,没有意义。您要是会但不愿意帮忙解决,那也没什么好说的。
在开发上,我确实是个新手。但我的专业和三年多的ERP的实施经验,在对ERP的理解上,判断客户需求是否合理上还是有一定自信的。
对于你的说法,本来是想一一反驳一下的,因为那种说法几乎只是哗众那种取宠而已。不过感觉没必要了,与我这个帖子讨论的无关。
我探讨的是技术问题,我关心的是首要是并发下 旧数据的修改 新数据的存储问题如何做。然后是其他的更深的扩展应用能否实现如何实现。
算了,不打口水仗了,没有意义。您要是会但不愿意帮忙解决,那也没什么好说的。
#17
非常感谢sp1234
首先说明确实不适合在asp.net中,因为除了问题7中的例子是我实际在编一个asp.net程序时碰到的实际情况,由此引发了其他所有我对于并发状态下的问题的考虑。其他的例子是结合我对其他产品如用友的了解而提的,确实应算作winform 只是没发现winform区。
我想,目前产生这些问题的核心是,不知道该怎么用。可确实看了许多资料了,都写的迷迷糊糊的。也无法验证,因为根本就看不出状态的变化,更别提有环境去测试执行结果了。
比如,书上,都会讲事务 锁 锁粒度 *协议等等。
但是,我不知道当我执行一条select 语句时,是否是上锁了,那种类型的锁。锁的是表 还是记录 还是数据库。这些都看不出来,也不知道如果我想对一个表上共享锁的话,该如何写。
还是在执行sql语句时,根据语句是select 还是insert 还是update 还是delete 。系统会自动根据语句来进行锁定。
所以 没有基本的应用 更无法提高了。
首先说明确实不适合在asp.net中,因为除了问题7中的例子是我实际在编一个asp.net程序时碰到的实际情况,由此引发了其他所有我对于并发状态下的问题的考虑。其他的例子是结合我对其他产品如用友的了解而提的,确实应算作winform 只是没发现winform区。
我想,目前产生这些问题的核心是,不知道该怎么用。可确实看了许多资料了,都写的迷迷糊糊的。也无法验证,因为根本就看不出状态的变化,更别提有环境去测试执行结果了。
比如,书上,都会讲事务 锁 锁粒度 *协议等等。
但是,我不知道当我执行一条select 语句时,是否是上锁了,那种类型的锁。锁的是表 还是记录 还是数据库。这些都看不出来,也不知道如果我想对一个表上共享锁的话,该如何写。
还是在执行sql语句时,根据语句是select 还是insert 还是update 还是delete 。系统会自动根据语句来进行锁定。
所以 没有基本的应用 更无法提高了。
#18
对了 问题3这种情况在我看来是绝对合理并且多次遇到的,我仅仅是就操作来讲。
因为许多客户的期初的数据量太大,而且,基本都是手工数据。初始化时基本上都只能靠手工录入。
可为了赶进度,经常是许多人同时录入,每人录入一部分。那么多人就会同时操作一个节点。操作中也不都是录入新数据。录一部分,会检查一下,错误的会修改掉。
别的产品我不知道,用友的库存期初,在录入 修改 查询是一个界面。当然别的地方也有报表可以查。
因为许多客户的期初的数据量太大,而且,基本都是手工数据。初始化时基本上都只能靠手工录入。
可为了赶进度,经常是许多人同时录入,每人录入一部分。那么多人就会同时操作一个节点。操作中也不都是录入新数据。录一部分,会检查一下,错误的会修改掉。
别的产品我不知道,用友的库存期初,在录入 修改 查询是一个界面。当然别的地方也有报表可以查。
#19
不太懂
帮你顶
帮你顶
#20
问题太多了,没读过这么长的文章,但用友的单据主子表不是通过单据号关联的,是通过id这一列关联的
#21
我靠,多好的学习机会
#22
还有每添加完一张单据后,系统就把单据号存储到一个表中,下次添加时再读取该表,而删除时就没这些操作,所以删除完会断号
#23
UP
#24
回复人:iamdazuiniao() ( 一级(初级)) 信誉:100
我让人帮我查了下u8的数据字典,确实,销售发票主表
Column Name Description Datatype Length Allow Nulls
SBVID 销售发票主表标识 int 4 False
cSBVCode 销售发票号 varchar 30 True
子表
SBVID 销售发票主表标识 int 4 False
AutoID 销售发票子表标识 int 4 False
所以,更疑惑了。我想主表标识应该是identity(1,1)的吧,那是不是意味着和我问题3的方式有点类似,插入主表,然后得到id,然后将id与明细信息插入子表?
我让人帮我查了下u8的数据字典,确实,销售发票主表
Column Name Description Datatype Length Allow Nulls
SBVID 销售发票主表标识 int 4 False
cSBVCode 销售发票号 varchar 30 True
子表
SBVID 销售发票主表标识 int 4 False
AutoID 销售发票子表标识 int 4 False
所以,更疑惑了。我想主表标识应该是identity(1,1)的吧,那是不是意味着和我问题3的方式有点类似,插入主表,然后得到id,然后将id与明细信息插入子表?
#25
up
#26
应该是这样,先得到主表最大id,插入主表信息,再得到子表autoid,连同主表id和子表信息一同插入子表,这些是我自己的观点,不一定对。至于并发什么的我也不懂,我只会用简单的事务。
#27
说得好!