Asp.net Devexpress ASPXGridView和EntityFramework 4.3.1的并发异常 我的问题
我有一个简单的WebForms项目来测试并发性 我正在使用:Asp.net Devexpress ASPXGridView和EntityFramework 4.3.1的并发异常 我的问题,asp.net,entity-framework,devexpress,optimistic-concurrency,Asp.net,Entity Framework,Devexpress,Optimistic Concurrency,我有一个简单的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 ASPXGr
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编辑同一条记录两次,我也会遇到并发异常
我得到的例外是:
系统数据优化并发异常
我的设置
**为了简洁起见,这里进行了简化
My code first实体的定义如下:
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]属性,ConcurrencRecny检查正在对该字段进行测试
在使用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
}
我还连接了一些按钮事件来测试直接concurrecny测试
乙二醇
乙二醇
这些按钮按预期工作。只有其他网格更新似乎有问题
可能是因为网格需要使用ObjectContect,而我的实体框架类使用的是DBContext
我尝试的修复
我在互联网上搜寻,试图找到一个解决办法。查看了DevExpress论坛,查看了StackOverflow上的其他帖子,互联网上的各种帖子,Microsoft MSDN关于并发性的文章,我就是无法解决这个问题
- 没有一个帖子像我的那样“简单”。他们都涉及其他数据。如一个主/细节 关系。自定义编辑器。等等。我使用所有内置的DevExpress控件,只显示一个 我的数据库表/实体上的单个网格视图
- 一些帖子建议刷新实体。我尝试了这个,但是得到一个异常,说实体是 未在对象状态管理器中跟踪
- 我试图通过销毁并重新创建对象上下文/db来刷新实体框架 但不知何故,我还是遇到了并发性问题
- 我尝试使用DBContexct和ObjectContext进行刷新。两者都不起作用。 (objContext.Refresh(RefreshMode.StoreWins,entity)。我要么得到一个声明的异常] 前面所说的实体未被跟踪,或者如果我告诉它仅刷新未修改的实体 然后什么也不发生(没有刷新,没有替换)
- 我尝试将我的DBContext设置为全局,但这并不好,因为WebForms似乎希望重新创建其 在每次web刷新后重新读取其网格数据上下文等。(页面加载,用户) 单击编辑,用户单击确定以更新)
彼得·梅斯我已经设法解决了我的问题 这可能不是最正确的解决方案,但它正在发挥作用,我们非常赞赏在这一点上取得的任何进展 方法
- 在ASPXGridView中发布数据后,我尝试刷新实体框架。 尝试了很多次,没有一次成功
- 我尝试在我的国家实体上使用TimeStamp属性,但是没有 似乎没有很好地映射到MySQL。(不过我现在可能会再试一次。) 我已经解决了这个问题)
- 然后我想可能是我的DevArt MySQL点连接器和MySQL出了问题。 因此,我切换到MSSQL及其标准连接器。这显示了相同的结果 我与MySQL&co.之间的问题
最后,我做了各种各样的尝试,注意到如果我去另一个地方 我的网站上的网页,然后再回来的问题没有发生 例如:
- 编辑国家/地区并保存。无问题
- 切换到其他站点页面
- 切换回国家/地区
- 编辑国家/地区并保存。无问题
> Set EntityDataSource.StoreOriginalValuesInViewState = FALSE
这停止了所有并发工作,因为没有存储旧的/预编辑的值,因此无法用于concurrecny检查 然后我想我会强制旧值成为编辑之前编辑器中的值。 我正在使用ASPXGridView.rowUpdate来执行此操作 我想没关系,我可以使用传递给ASPXGridView.rowView的旧值更新 确保实体框架良好运行 这样做我发现了一些非常奇怪的行为 如果我: A的帖子之所以成功,是因为A上的旧值被神奇地更新了 对于B发布的新值 请记住,A上的编辑表单一直处于打开状态,因此它不应该更新其下面的旧值。我不知道为什么会发生这种情况。非常奇怪 可能只有在 编辑表单正在关闭
不管怎样,然后我想。好吧,我会解决这个奇怪的问题。所以我创造了 网页上存储my Country实体副本的静态成员 当用户打开编辑器时,我获取当前值并存储它们 然后,当启动ASPXGridView.rowUpdate时,我将存储的旧值推回到 OldValues数据。(我还更新了我的timstamp。)/
- Get Entity
- Update Entity
- Save Entity
- No issue.
- Get Entity again.
- Update Entity again.
- Save Entity again.
- No issue.
> Set EntityDataSource.StoreOriginalValuesInViewState = FALSE
- open edit form in browser A
- open edit form in browser B
- save changes in browser B (DB updates with new values here)
- save changes in browser A (DB updated here too. but should have been a
concurrency exception!)
private static Country editCountry = null;
protected void dbgCountries_StartRowEditing(object sender, DevExpress.Web.Data.ASPxStartRowEditingEventArgs e)
{
if (editCountry == null)
{
editCountry = new Country();
}
var context = new MyDBContext();
var currCountry = context.Countries.Where(c => c.CountryID == (int)(e.EditingKeyValue)).Single();
editCountry.CopyFrom(currCountry);
}
protected void dbgCountries_RowUpdating(object sender, DevExpress.Web.Data.ASPxDataUpdatingEventArgs e)
{
//Ensure old values are populated
e.OldValues["RowVersion"] = editCountry.RowVersion;
//No need to set other old values as I am only testing against
//the one field for concurrency.
//On row updating ensure RowVersion is set.
//This is the field being used for the concurrency check.
DateTime date = DateTime.Now;
var s = date.ToString("yyyy-MM-dd HH:mm:ss");
e.NewValues["RowVersion"] = s;
}