如果我的WinForm是很多用户同时操作的一个系统
试问
如果一个用户做了对数据的操作(新增,修改,删除)
其实用户不用点刷新就能立刻知道
在界面上能够及时显示
比如说,一个用户对数据做了修改,这时另一个用户没点刷新
他不知道,也去做了修改,以此类推
我一直觉得这样是很不好的
有什么好的开发思路吗?

解决方案 »

  1.   

    不点刷新,那你就定时帮他刷新喽
    timer
      

  2.   

    这是事务的问题,不是Winform的问题。具体方案取决于需求,我做过的经验是谁先提交就算谁成功,后面那个及时提醒它数据已更改,让它更新了再做修改
      

  3.   

    当然A用户编辑的时候也可以把表锁住,这样其他用户就不能访问也就不能同时更改了,但是这样做对长事务是不现实的,总不能让B一直就那么等着A释放吧
      

  4.   

    我们是用XML文件定时广播刷新的。。
      

  5.   

    开个线程对数据进行监视,如果有改动发出提示,刷新数据
    sql server里好像有事件探查器
    具体怎么样我也不是很清楚
      

  6.   

    用vss吗,每个人保存自己的修改,并定时获取最新版本
      

  7.   

    用事务 这是必须的 我的系统都用了
    但达不到效果
    如果你把数据修改了,如果其他用户能及时知道,他应该是根据你修改的数据做出操作
    这样才符合逻辑
    如果用timer 不好,这个方法太笨 而且会慢的要死 
    5,8,9楼的方法很有建设性
    希望有谁能提出更加详细的方案
    我想这个问题是谁都会碰到的
    目前我的做法的就没对他处理
    他不按刷新 那是他自己的事
    反正对数据的操作的时候用了事务处理,不会发生数据异常
    但感觉这样总不能给用户带来实际的体验
      

  8.   

    不是让你去用数据库的事务,是说你自己实现长事务。8楼的方法可行,但是线程监视也不可能回避这个问题,一个线程多久看一次,发现冲突怎么处理,你都要考虑,所以代价不一定低。
    9楼的方法本质上是让你用观察者模式,把每个观察者都注册到你的控制器中,当某个观察者去修改某条数据,则通知所有人, 参照一下设计模式的Observer模式,它的第二种“拉”的方式对于Winform没必要,纯浪费资源。不过这种方式你要考虑清楚了,谁喜欢在编辑一个数据半天了突然弹出一个对话框说该记录被别人改了,你的改动无效。所以你最好是能自己实现你的事务,在某个用户编辑某条记录就不再允许他人编写,谁先开始编辑就锁住记录其他人就不能再编辑,.Net的锁机制会让你很容易实现这个。自己再考虑一下吧
      

  9.   

    最好是数据库能通知你。
    sql2005好像可以
      

  10.   

    过奖了,同是正在发展中的菜鸟,呵呵。
    窗体只是界面,显示数据的工具而已,观察者还是要到后台实现,不知道host的架构,刚想起来如果是server/client这样的,运行程序根本就不是在同一台机器上(大约也是如此),所以Observer模式的实现还需要看你的系统架构,要么远程方法(对象)调用,要我就用.Net Remoting了,要是你服务器用的Web Service,则真的要用拉模型了,因为http没有很好的注册机制, 隔段时间去问问服务器是不是有更新,要是真的是所有客户端都访问一个数据库而没有服务器的话这是够经典的架构啊,我觉得这样的设计本身就是有问题的,看高手怎么解决吧,我想不出很好的方法。如果是实现长事务,用服务器实现锁的功能,客户端请求的时候注意把资源锁起来,其他客户访问的时候要么等待要么返回资源被锁定的信息,好好设计一下这种线程同步的机制,服务器Serve本来就是并发的,应该是可以实现的
      

  11.   

    这个问题是够麻烦的
    CyberKnightGIC  讲的还算有依有据的 而且也很有建设性的
    但听起来还是比较笼统,不知道从何下手
    我不知道其他做winform开发的朋友怎么处理
    这有点像真实的火车售票系统
    那么多窗口同时在售票
    我想每一个窗口做出售票动作的时候,其他窗口应该能及时得到最新的数据
    要不然应该会发生这样状况
    两个窗口同时查到了到一个地方的票的界面,发现还有一张
    结果一个窗口先卖了,另一个由于没点刷新
    也认为有,他告知买票者 还有
    当人家付了钱,给他时,他点下售票,发现已经是0
    这样他应该要挨骂吧,你刚才还告诉我有呢
      

  12.   

    业务逻辑中应该有个查询锁定的概念,也就是用户查询到需要售出的票时,实际是对这个数据的一个独占,其他用户无法再访问。然后再决定是售出还是释放。
    一般用户不是非常多的时候,timer是可以胜任的。
    当然,火车售票系统不是用的timer。因为他一次只能查询一个车次。不会出现大面积数据锁定。
      

  13.   

    用户2就不会执行,直接收到错误该记录正在编写中。如果是短事务,可以让用户2等待1执行完毕再执行,如果长事务,用户2就不需要等待,直接告诉2事务正在执行中。业务逻辑本身也包含事务控制啊,事务只是一个概念,只要满足ACID都可以啊,呵呵,不是这样理解吗?当然这个最终流程还是要看楼主的业务需求了。楼主所说的火车票系统,还真是一个很好的例子,春节的时候就有刚刚查还有票出票的时候就没有了的,不晓得楼主有这样的经历没,我是看到过的,还扯皮的:)。其实解决方案还是看你的需求,锁的实现很简单,.Net用lock就可以了(Server端的代码),你说的问题本身需要框架的支持,是有些复杂的。首先你要有一个ID Map(请参考一下Martin Fowler的大作企业应用架构模式的Identity Map模式。)然后你需要载入的这些对象的每个都有一个锁变量,当访问这个变量的时候获知当前其状态,如果要编辑则以独占方式(lock这个变量)将其设置为占用,每个线程要想用这个记录则先要获取锁状态,被编辑的,则不能访问或者告之客户端被编辑了,客户端显示一个该记录被lock信息。正在编辑的对象改完了则释放锁,这样大家再次需要访问的时候就可以正常访问了,因为你用了锁,所以永远都只有一个对象能编辑到这个对象,而其他对象则只读不能改。操作系统原理里面的Reader-Writer模型会给你更多的启示,相信这个你肯定能做到的.
      

  14.   

    你们给我的启发都很大  特别是 CyberKnightGIC 
    就是不知道怎么去做,要有点参考就好了
    我想这个问题基本上搞开发的人
    我们公司的系统都是没去做处理
    自己不点刷新  不管
    但我决定假数据现象会给用户带来很多麻烦
    有时候你增了一条纪录,其他本可以不去增,但因为没点刷新
    还是增了,当点确定的时候才发现主键重复了,该纪录已被添加
    很恼火,白做了这么久~~~~
      

  15.   

    呵呵,查到就别人就不能再买了没有别的意思,别误会我啊,不过我觉得你肯定没有在紧张的时候买过票:),部分同意你的观点就是锁及业务逻辑,我上文说的就是这个意思,timer和大面积数据锁定就不太理解了,怎么会大面积锁定呢,另外timer只是访问的一种方式而已,就算用事件也是可以的,取决与你的需求。放假了,回家了,过了假期再来看了,大家十一快乐啊
      

  16.   


    很好的理念。可以参看:http://blog.csdn.net/fzy816/archive/2006/12/18/1448096.aspx乐观的做法,简单来说,数据要有一个“时间戳”标记(例如取DateTime.Now.Ticks),在更新之前要重新读取后台的这个时间戳来预先判断一下。
      

  17.   

    没研究过,但是微软的WCF平台呢?听说好像可以实现Remoting不能实现的一些功能,不过自己还没具体看过WCF,只是听过一点。
      

  18.   

    如果连接的SQL 系统是有机制自动管理的。
      

  19.   

    恩,大概是这个意思,这算是悲观的做法吧,但是不会出现查到了买不到的现象。
    大面积锁定大概说的不准确,比如买票的时候,可能一个用户会锁定非常多的票,但是又没有卖,这时候会严重影响其他人的操作。也就是别人买不到票了。
    我真的没在紧张的时候买过票,因为过年的时候根本就买不到:)
    但是我在紧张的时候卖过票,比如进3年的上海网球大师杯的票就是这种方式卖掉的。
    Timer只是一个刷新的方式,相比较广播而言,对服务器的压力没那么大。
    其实多用户系统都不能用广播或者客户端时刻都刷新,服务器肯定会受不了的。用timer,每秒钟服务器都要接收很多客户端信息,用广播更吓人,每个用户的数据操作都要返回给所有用户。
      

  20.   

    如果要通过事务只是防止数据紊乱而不用考虑界面即时刷新的话可以用事务级别来控制http://blog.csdn.net/idda/archive/2007/09/12/1782105.aspx
    隔离级别的概念企业级的数据库每一秒钟都可能应付成千上万的并发访问,因而带来了并发控制的问题。由数据库理论可知,由于并发访问,在不可预料的时刻可能引发如下几个可以预料的问题:  脏读:包含未提交数据的读取。例如,事务1 更改了某行。事务2 在事务1 提交更改之前读取已更改的行。如果事务1 回滚更改,则事务2 便读取了逻辑上从未存在过的行。  不可重复读取:当某个事务不止一次读取同一行,并且一个单独的事务在两次(或多次)读取之间修改该行时,因为在同一个事务内的多次读取之间修改了该行,所以每次读取都生成不同值,从而引发不一致问题。  幻象:通过一个任务,在以前由另一个尚未提交其事务的任务读取的行的范围中插入新行或删除现有行。带有未提交事务的任务由于该范围中行数的更改而无法重复其原始读取。如你所想,这些情况发生的根本原因都是因为在并发访问的时候,没有一个机制避免交叉存取所造成的。而隔离级别的设置,正是为了避免这些情况的发生。事务准备接受不一致数据的级别称为隔离级别。隔离级别是一个事务必须与其它事务进行隔离的程度。较低的隔离级别可以增加并发,但代价是降低数据的正确性。相反,较高的隔离级别可以确保数据的正确性,但可能对并发产生负面影响。根据隔离级别的不同,DBMS为并行访问提供不同的互斥保证。在SQL Server数据库中,提供四种隔离级别:未提交读、提交读、可重复读、可串行读。这四种隔离级别可以不同程度地保证并发的数据完整性:隔离级别          未提交读          提交读       可重复读    可串行读
     脏读               是                否            否         否
     不可重复读取       是                是            否         否
     幻像               是                是            是         否
     
    可以看出,“可串行读”提供了最高级别的隔离,这时并发事务的执行结果将与串行执行的完全一致。如前所述,最高级别的隔离也就意味着最低程度的并发,因此,在此隔离级别下,数据库的服务效率事实上是比较低的。尽管可串行性对于事务确保数据库中的数据在所有时间内的正确性相当重要,然而许多事务并不总是要求完全的隔离。例如,多个作者工作于同一本书的不同章节。新章节可以在任意时候提交到项目中。但是,对于已经编辑过的章节,没有编辑人员的批准,作者不能对此章节进行任何更改。这样,尽管有未编辑的新章节,但编辑人员仍可以确保在任意时间该书籍项目的正确性。编辑人员可以查看以前编辑的章节以及最近提交的章节。这样,其它的几种隔离级别也有其存在的意义。在.net框架中,事务的隔离级别是由枚举System.Data.IsolationLevel所定义的: