【发布时间】:2012-09-05 04:54:24
【问题描述】:
我的问题
我有一个用于测试并发性的简单 WebForms 项目。
我正在使用:
1. Entity Framework 4.3.1 code first approach.
2. DevExpress ASP.net controls to visualize my data. Specifically an ASPXGridView control.
3. MySQL as database backend.
现在我遇到了并发检查问题。
即使我是唯一编辑数据的用户,如果我使用 DevExpress ASPXGridView 两次编辑同一记录,我也会遇到并发异常!
我得到的例外是: System.Data.OptimisticConcurrencyException
我的设置
** 为简洁起见,此处简化
我的代码优先实体是这样定义的:
public class Country
{
//Some constructors here
[Required, ConcurrencyCheck]
public virtual string LastUpdate { get; set; }
[Required, Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public virtual int CountryID { get; set; }
//Various other data fields here
}
您可以看到我添加了一个名为 LastUpdate 的字段,由于设置了 [ConcurrencyCheck] 属性,正在测试并发检查。
在我的带有 DevExpress ASPXGridView 的网页上,我使用 EntityDataSource 在网格视图和实体框架之间进行绑定。网格视图正在使用弹出编辑器。我有以下事件:
protected void Page_Load(object sender, EventArgs e)
{
//Hook entity datasource to grid view
dbgCountries.DataSource = CountriesEntityDataSource;
dbgCountries.DataBind();
}
protected void CountriesEntityDataSource_ContextCreating(object sender, EntityDataSourceContextCreatingEventArgs e)
{
//Create and hook my DBContext class to the entity
//datasources ObjectContext property.
var context = new MyDBContextClass();
e.Context = ((IObjectContextAdapter)context ).ObjectContext;
}
protected void dbgCountries_InitNewRow(object sender, DevExpress.Web.Data.ASPxDataInitNewRowEventArgs e)
{
//I create a new MyDBContextClass here and use it
//to get the next free id for the new record
}
protected void dbgCountries_CustomErrorText(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewCustomErrorTextEventArgs e)
{
//My code to catch the System.Data.OptimisticConcurrencyException
//excpetion is in here.
//I try to rtefresh the entity here to get the latest data from
//database but I get an exception saying the entity is not being
//tracked
}
protected void dbgCountries_RowValidating(object sender, DevExpress.Web.Data.ASPxDataValidationEventArgs e)
{
//Basic validation of record update in here
}
protected void dbgCountries_RowUpdating(object sender, DevExpress.Web.Data.ASPxDataUpdatingEventArgs e)
{
//I set the LastUpdate field (my concurrency field)
//to the current time here
}
我还连接了一些按钮事件来测试直接并发测试。
例如
- Get Entity
- Update Entity
- Update DB directly with sql
- Save Entity
- Get concurrency exception as expected
例如
- Get Entity
- Update Entity
- Save Entity
- No issue.
- Get Entity again.
- Update Entity again.
- Save Entity again.
- No issue.
这些按钮按预期工作。只有网格更新似乎有问题。
可能是因为网格需要使用ObjectContect,而我的实体框架类使用的是DBContext?
我尝试的修复
我搜索了互联网试图找到解决方案。检查了 DevExpress 论坛,检查了 StackOverflow 上的其他帖子,互联网上的各种帖子,Microsoft MSDN 关于并发的文章,我就是无法解决这个问题。
没有一个帖子像我的那样“简单”。他们都涉及其他数据。例如主/详细信息 关系。自定义编辑器。等等我正在使用所有内置的 DevExpress 控件,只显示一个 我的数据库表/实体上的单个网格视图。
一些帖子建议刷新实体。我试过这个但得到一个异常说实体是 在对象状态管理器中没有被跟踪。
我尝试通过销毁和重新创建我的对象上下文/数据库来刷新实体框架 上下文,但不知何故我仍然遇到并发问题。
我尝试使用 DBContext 和 ObjectContext 进行刷新。都没有奏效。 (objContext.Refresh(RefreshMode.StoreWins,实体)。我要么得到一个异常,如所述] 早些时候说实体没有被跟踪,或者如果我告诉它只刷新非修改 实体然后什么都没有发生(没有刷新,没有异常)
我尝试将我的 DBContext 设为全局,但这并不好,因为 WebForms 似乎想要重新创建它 整个状态并在每次网络刷新后重新挂钩其网格数据上下文等。 (页面加载,用户 点击编辑,用户点击确定更新)
现在所有这些解决方案似乎都考虑了在并发异常之后要做什么。看到我什至不应该首先得到异常,我想他们不会有帮助。
建议
你们有没有关于如何完成这项工作的建议?
从网格发布数据后,我是否必须强制实体框架手动刷新? (我现在才想到这个)
我的设置似乎很简单。也许我错过了一些非常明显的东西。我还没有过多地使用 WebForms 或 EntityFramework,所以可能缺少一些简单(而且可能很明显)的解决方案?
任何帮助表示赞赏。
谢谢 彼得·梅斯
【问题讨论】:
标签: asp.net entity-framework devexpress optimistic-concurrency