*不*使用 Devart 获取 ChangeConflictException
*Not* getting ChangeConflictException using Devart
我正在调查间歇性出现的 Devart.Data.Linq.ChangeConflictException: Row not found or changed
。
我一直在阅读有关 concurrency conflicts 的 Devart 文章,作为起点,我正在尝试重现并发冲突。使用包含的基于 MS 的 LINQ 类 这很容易做到(使用下面的代码结构可以成功做到)。然而,即使按照他们在文章中的示例,我也无法产生异常。我试过了
- 完全按照他们的文章中所示使用 ADO 参数化查询
- 使用如下所示的简化 ADO 查询(不担心测试期间的注入攻击)
- 在新上下文中使用 LinqConnect(也在他们的文章中建议)。
- 使用调试器暂停执行并使用 MySQL Workbench.
手动更新 table
这是我使用的测试代码:
public static void MySqlTest()
{
using (MySqlDataContext db = new MySqlDataContext())
{
Customer customer = db.Customers.First(c => c.Username.Equals("ian2"));
MySqlAdoChange(db.Connection);
//MySqlLinqConnectChange();
customer.Address1 = "Original change" + DateTime.UtcNow.Ticks;
db.SubmitChanges();
}
}
public static void MySqlAdoChange(DbConnection connection)
{
connection.Open();
var command = connection.CreateCommand();
command.CommandText = "UPDATE customers SET Address1 = 'Conflicting change" + DateTime.UtcNow.Ticks + "' WHERE Username = 'ian2'";
command.ExecuteNonQuery();
}
public static void MySqlLinqConnectChange()
{
using (MySqlDataContext db = new MySqlDataContext())
{
Customer customer = db.Customers.First(c => c.Username.Equals("ian2"));
customer.Address1 = "Conflicting change" + DateTime.UtcNow.Ticks;
db.SubmitChanges();
}
}
更奇怪的是保存到数据库的值在两者之间交替!
我必须将 DateTime 标记附加到末尾以确保唯一性,否则它会优化我的更新,并且只会更新成为当前未激活的值。
任何人都可以解释这种行为吗?为什么我不能生成 ChangeConflictException?
首先请注意,在您的示例代码中,您在 MySqlTest
函数中更新了 Phone
字段,但在 MySqlAdoChange
函数中更新了 Address1
字段,因此不会有任何冲突.
但是,很可能即使您更正了此问题,您也不会有更新冲突。如果您查看 Customer
class 源代码,在 Phone
属性,您(很可能)会看到它用带有 UpdateCheck = UpdateCheck.Never
的 Column 属性装饰(这是默认值:请参阅此处 https://www.devart.com/linqconnect/docs/MemberMapping.html)。因此,默认情况下,LinqConnect 不会检查您的字段的更新冲突,除非您通过使用 UpdateCheck = UpdateCheck.Always
或 UpdateCheck.WhenChanged
修饰来告诉它要检查哪些字段。当然,您不应该直接修改源代码,而应该在模型设计器中更改 属性。
我正在调查间歇性出现的 Devart.Data.Linq.ChangeConflictException: Row not found or changed
。
我一直在阅读有关 concurrency conflicts 的 Devart 文章,作为起点,我正在尝试重现并发冲突。使用包含的基于 MS 的 LINQ 类 这很容易做到(使用下面的代码结构可以成功做到)。然而,即使按照他们在文章中的示例,我也无法产生异常。我试过了
- 完全按照他们的文章中所示使用 ADO 参数化查询
- 使用如下所示的简化 ADO 查询(不担心测试期间的注入攻击)
- 在新上下文中使用 LinqConnect(也在他们的文章中建议)。
- 使用调试器暂停执行并使用 MySQL Workbench. 手动更新 table
这是我使用的测试代码:
public static void MySqlTest()
{
using (MySqlDataContext db = new MySqlDataContext())
{
Customer customer = db.Customers.First(c => c.Username.Equals("ian2"));
MySqlAdoChange(db.Connection);
//MySqlLinqConnectChange();
customer.Address1 = "Original change" + DateTime.UtcNow.Ticks;
db.SubmitChanges();
}
}
public static void MySqlAdoChange(DbConnection connection)
{
connection.Open();
var command = connection.CreateCommand();
command.CommandText = "UPDATE customers SET Address1 = 'Conflicting change" + DateTime.UtcNow.Ticks + "' WHERE Username = 'ian2'";
command.ExecuteNonQuery();
}
public static void MySqlLinqConnectChange()
{
using (MySqlDataContext db = new MySqlDataContext())
{
Customer customer = db.Customers.First(c => c.Username.Equals("ian2"));
customer.Address1 = "Conflicting change" + DateTime.UtcNow.Ticks;
db.SubmitChanges();
}
}
更奇怪的是保存到数据库的值在两者之间交替!
我必须将 DateTime 标记附加到末尾以确保唯一性,否则它会优化我的更新,并且只会更新成为当前未激活的值。
任何人都可以解释这种行为吗?为什么我不能生成 ChangeConflictException?
首先请注意,在您的示例代码中,您在 MySqlTest
函数中更新了 Phone
字段,但在 MySqlAdoChange
函数中更新了 Address1
字段,因此不会有任何冲突.
但是,很可能即使您更正了此问题,您也不会有更新冲突。如果您查看 Customer
class 源代码,在 Phone
属性,您(很可能)会看到它用带有 UpdateCheck = UpdateCheck.Never
的 Column 属性装饰(这是默认值:请参阅此处 https://www.devart.com/linqconnect/docs/MemberMapping.html)。因此,默认情况下,LinqConnect 不会检查您的字段的更新冲突,除非您通过使用 UpdateCheck = UpdateCheck.Always
或 UpdateCheck.WhenChanged
修饰来告诉它要检查哪些字段。当然,您不应该直接修改源代码,而应该在模型设计器中更改 属性。