【发布时间】:2014-08-29 23:27:06
【问题描述】:
我在使用 EF6 和 MySQL 进行并发检查时遇到问题。
我遇到的问题是当我尝试将数据保存到数据库时引发并发异常。如果您检查输出到控制台的 sql,它会尝试使用 where 子句中的旧值从数据库中查询并发字段。因为这个字段已经被数据库更新了。
环境:
- Windows 7 64 位
- Visual Studio 2013
已安装 Nuget 包:
- EF 6.0.1
- MySql.ConnectorNET.Data 6.8.3.2
- MySql.ConnectorNET.Entity 6.8.3.2
演示数据库 SQL:
DROP DATABASE IF EXISTS `bugreport`;
CREATE DATABASE IF NOT EXISTS `bugreport`;
USE `bugreport`;
DROP TABLE IF EXISTS `test`;
CREATE TABLE IF NOT EXISTS `test` (
`TestId` int(10) NOT NULL AUTO_INCREMENT,
`AStringField` varchar(50) DEFAULT NULL,
`DateModified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`TestId`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
INSERT INTO `test` (`TestId`, `AStringField`, `DateModified`) VALUES
(1, 'Initial Value', '2014-07-11 09:15:52');
演示代码:
using System;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
namespace BugReport
{
class Program
{
static void Main(string[] args)
{
using (var context = new BugReportModel())
{
context.Database.Log = (s => Console.WriteLine(s));
var firstTest = context.tests.First();
firstTest.AStringField = "First Value";
// Exception is thrown when changes are saved.
context.SaveChanges();
Console.ReadLine();
}
}
}
public class BugReportModel : DbContext
{
public BugReportModel()
: base("name=Model1")
{
}
public virtual DbSet<test> tests { get; set; }
}
[Table("test")]
public class test
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int TestId { get; set; }
[StringLength(50)]
public string AStringField { get; set; }
[ConcurrencyCheck()]
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
[Column(TypeName = "timestamp")]
public System.DateTime DateModified { get; set; }
}
}
更新: 用 MySql 归档 bug。
【问题讨论】:
-
代码优先?为什么读取行后并发字段会发生变化?如果 EF 中标记为 Concurrency 的字段在读取后和更新之前发生更改,则 EF 确实正确抛出 Concurrency 异常
-
我阅读了该行,然后在下一行修改它。保存更改会引发异常。修改记录应该更新并发字段(即 rowversion)。我试图通过将 context.SaveChanges() 调用包装在 Try-Catch 块中以显示引发的异常来引起对它的注意。
-
是的,在这种情况下它是 Code First。
-
不能更改并发字段
-
这就是我修改'AStringField'的原因。
标签: mysql entity-framework concurrency entity-framework-6