I'm developing a webapp that allows the editing of records. There is a possibility that two users could be working on the same screen at a time and I want to minimise the damage done, if they both click save.
我正在开发一个允许编辑记录的webapp。两个用户有可能一次在同一个屏幕上工作,如果他们都点击保存,我想尽量减少损坏。
If User1 requests the page and then makes changes to the Address, Telephone and Contact Details, but before he clicks Save, User2 requests the same page.
如果User1请求页面然后更改地址,电话和联系人详细信息,但在他单击“保存”之前,User2请求同一页面。
User1 then clicks save and the whole model is updated using TryUpdateModel(), if User2 simply appends some detail to the Notes field, when he saves, the TryUpdateModel() method will overwrite the new details User1 saved, with the old details.
然后User1单击保存并使用TryUpdateModel()更新整个模型,如果User2只是将一些细节附加到Notes字段,当他保存时,TryUpdateModel()方法将使用旧的详细信息覆盖User1保存的新细节。
I've considered storing the original values for all the model's properties in a hidden form field, and then writing a custom TryUpdateModel to only update the properties that have changed, but this feels a little too like the Viewstate we've all been more than happy to leave behind by moving to MVC.
我已经考虑将所有模型属性的原始值存储在隐藏的表单字段中,然后编写自定义的TryUpdateModel以仅更新已更改的属性,但这感觉有点像Viewstate我们已经超过了很高兴能够转移到MVC。
Is there a pattern for dealing with this problem that I'm not aware of?
是否有处理这个问题的模式,我不知道?
How would you handle it?
你会怎么处理它?
Update: In answer to the comments below, I'm using Entity Framework.
更新:在回答下面的评论时,我正在使用实体框架。
Anthony
4 个解决方案
#1
Unless you have any particular requirements for what happens in this case (e.g. lock the record, which of course requires some functionality to undo the lock in the event that the user decides not to make a change) I'd suggest the normal approach is an optimistic lock:
除非你对这种情况下发生的事情有任何特殊要求(例如锁定记录,当然需要一些功能来在用户决定不做更改的情况下撤销锁定)我建议正常的方法是乐观锁定:
Each update you perform should check that the record hasn't changed in the meantime.
您执行的每个更新都应检查记录在此期间是否未更改。
So:
- Put an integer "version" property or a guid / rowversion on the record.
- Ensure this is contained in a hidden field in the html and is therefore returned with any submit;
- When you perform the update, ensure that the (database) record's version/guid/rowversion still matches the value that was in the hidden field [and add 1 to the "version" integer when you do the update if you've decided to go with that manual approach.]
在记录上放置一个整数“version”属性或guid / rowversion。
确保它包含在html中的隐藏字段中,因此随任何提交一起返回;
执行更新时,请确保(数据库)记录的版本/ guid / rowversion仍然与隐藏字段中的值匹配[并且如果您决定进行更新,则在执行更新时将“1”添加到“版本”整数用这种手动方法。]
A similar approach is obviously to use a date/time stamp on the record, but don't do that because, to within the accuracy of your system clock, it's flawed.
类似的方法显然是在记录上使用日期/时间戳,但不要这样做,因为在系统时钟的准确性范围内,它是有缺陷的。
[I suggest you'll find fuller explanations of the whole approach elsewhere. Certainly if you were to google for information on NHibernate's Version functionality...]
[我建议你会在其他地方找到更全面的解释。当然,如果你要谷歌获取有关NHibernate版本功能的信息...]
#2
Locking modification of a page while one user is working on it is an option. This is done in some wiki software like dokuwiki. In that case it will usually use some javascript to free the lock after 5-10 minutes of inactivity so others can update it.
在一个用户正在处理页面时锁定对页面的修改是一种选择。这是在dokuwiki等一些wiki软件中完成的。在这种情况下,通常会使用一些javascript来在5-10分钟不活动后释放锁定,以便其他人可以更新它。
Another option might be storing all revisions in a database so when two users submit, both copies are saved and still exist. From there on, all you'd need to do is merge the two.
另一个选项可能是将所有修订存储在数据库中,这样当两个用户提交时,两个副本都会保存并仍然存在。从那以后,你需要做的就是合并两者。
#3
You usually don't handle this. If two users happen to edit a document at the same time and commit their updates, one of them wins and the other looses.
你通常不会处理这个问题。如果两个用户碰巧同时编辑文档并提交更新,则其中一个用户获胜而另一个用户失败。
Resources lockout can be done with stateful desktop applications, but with web applications any lockout scheme you try to implement may only minimize the damage but not prevent it.
资源锁定可以通过有状态桌面应用程序完成,但是对于Web应用程序,您尝试实现的任何锁定方案可能只会最小化损坏但不会阻止它。
Don't try to write an absolutely perfect and secure application. It's already good as it is. Just use it, probably the situation won't come up at all.
不要试图写一个绝对完美和安全的应用程序。它已经很好了。只要使用它,可能情况根本不会出现。
#4
If you use LINQ to SQL as your ORM it can handle the issues around changed values using the conflicts collection. However, essentially I'd agree with Mastermind's comment.
如果使用LINQ to SQL作为ORM,它可以使用冲突集合处理更改值的问题。但是,基本上我同意Mastermind的评论。
#1
Unless you have any particular requirements for what happens in this case (e.g. lock the record, which of course requires some functionality to undo the lock in the event that the user decides not to make a change) I'd suggest the normal approach is an optimistic lock:
除非你对这种情况下发生的事情有任何特殊要求(例如锁定记录,当然需要一些功能来在用户决定不做更改的情况下撤销锁定)我建议正常的方法是乐观锁定:
Each update you perform should check that the record hasn't changed in the meantime.
您执行的每个更新都应检查记录在此期间是否未更改。
So:
- Put an integer "version" property or a guid / rowversion on the record.
- Ensure this is contained in a hidden field in the html and is therefore returned with any submit;
- When you perform the update, ensure that the (database) record's version/guid/rowversion still matches the value that was in the hidden field [and add 1 to the "version" integer when you do the update if you've decided to go with that manual approach.]
在记录上放置一个整数“version”属性或guid / rowversion。
确保它包含在html中的隐藏字段中,因此随任何提交一起返回;
执行更新时,请确保(数据库)记录的版本/ guid / rowversion仍然与隐藏字段中的值匹配[并且如果您决定进行更新,则在执行更新时将“1”添加到“版本”整数用这种手动方法。]
A similar approach is obviously to use a date/time stamp on the record, but don't do that because, to within the accuracy of your system clock, it's flawed.
类似的方法显然是在记录上使用日期/时间戳,但不要这样做,因为在系统时钟的准确性范围内,它是有缺陷的。
[I suggest you'll find fuller explanations of the whole approach elsewhere. Certainly if you were to google for information on NHibernate's Version functionality...]
[我建议你会在其他地方找到更全面的解释。当然,如果你要谷歌获取有关NHibernate版本功能的信息...]
#2
Locking modification of a page while one user is working on it is an option. This is done in some wiki software like dokuwiki. In that case it will usually use some javascript to free the lock after 5-10 minutes of inactivity so others can update it.
在一个用户正在处理页面时锁定对页面的修改是一种选择。这是在dokuwiki等一些wiki软件中完成的。在这种情况下,通常会使用一些javascript来在5-10分钟不活动后释放锁定,以便其他人可以更新它。
Another option might be storing all revisions in a database so when two users submit, both copies are saved and still exist. From there on, all you'd need to do is merge the two.
另一个选项可能是将所有修订存储在数据库中,这样当两个用户提交时,两个副本都会保存并仍然存在。从那以后,你需要做的就是合并两者。
#3
You usually don't handle this. If two users happen to edit a document at the same time and commit their updates, one of them wins and the other looses.
你通常不会处理这个问题。如果两个用户碰巧同时编辑文档并提交更新,则其中一个用户获胜而另一个用户失败。
Resources lockout can be done with stateful desktop applications, but with web applications any lockout scheme you try to implement may only minimize the damage but not prevent it.
资源锁定可以通过有状态桌面应用程序完成,但是对于Web应用程序,您尝试实现的任何锁定方案可能只会最小化损坏但不会阻止它。
Don't try to write an absolutely perfect and secure application. It's already good as it is. Just use it, probably the situation won't come up at all.
不要试图写一个绝对完美和安全的应用程序。它已经很好了。只要使用它,可能情况根本不会出现。
#4
If you use LINQ to SQL as your ORM it can handle the issues around changed values using the conflicts collection. However, essentially I'd agree with Mastermind's comment.
如果使用LINQ to SQL作为ORM,它可以使用冲突集合处理更改值的问题。但是,基本上我同意Mastermind的评论。