環境:
mysql5.5
.Net Connector 6.6.4
EF 4.3.1
模型要求:
很多業務要求並發處理,時間戳是個很好的選擇.
代碼如下:
public class Test { public int ID { get; set; } public string Name { get; set; } public byte[] LastChanged { get; set; } }
問題描述:在LastChanged屬性用Data Annotations標記[Timestamp]
[Timestamp] public byte[] LastChanged { get; set; }
或者Fluent API中配置成IsRowVersion()
DbModelBuilder 作如下配置
modelBuilder.Entity<Test>().Property(p => p.LastChanged).IsRowVersion();
或者EnityTypeConfiguration<T>類中配置
Property(p=>p.LastChanged).IsRowVersion();
在Migration的時候 會有錯誤,如下:
錯誤 0040: 類型 rowversion 未使用命名空間或別名進行限定。只有 PrimitiveType 才可以在不限定的情況下使用。
原因是 MySqlMigrationSqlGenerator不允許byte[]類型上標記TimeStamp/RowVersion
那應該用什么類型?
database first來看看 這里就不截圖 加表 設置字段類型 TIMESTAMP 默認值 CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
生成EDM 類型 為Datetime 這和MsSql是有區別的
現在修改模型
public class Test { public int ID { get; set; } public string Name { get; set; } public DateTime LastChanged { get; set; } }
編譯下代碼 不能通過 EF的.IsRowVersion()方法不能作用於DateTime類型的屬性.
修改DbModelBuilder代碼:
Property(p => p.LastChanged).IsConcurrencyToken();
再次Migration 並且 update-database 去查看數據庫的表結構
問題又來了 LastChanged的數據庫類型成Datetime了
我們手動來解決這個問題
修改DbMigration中的Up方法的代碼
源代碼如下:
AddColumn("Tests", "LastChanged", c => c.DateTime(nullable: false);
修改為
AddColumn("Tests", "LastChanged", c => c.DateTimeOffset(nullable: false, defaultValueSql: "CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"));
update-database后 檢查表結構 ok!沒有問題了
測試下
using (var db = new BlogContext()) { db.Tests.Add(new Test { Name = "Test01" }); db.SaveChanges(); }
是不是又異常了 看詳細信息 原來把LastChanged字段的值更新回數據庫了 這不是我們預期了
再去修改下DbModelBuilder代碼:
Property(p => p.LastChanged).IsConcurrencyToken().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
再測試 ok! 通過
以上代碼是成功后再添加的 如有問題 請指出
再來總結下mysql下使用code first時 時間戳類型 要注意的幾點
1.模型中的類型 必須為datetime
2.使用IsConcurrencyToken()方法
3.up腳本修改 AddColumn("Tests", "LastChanged", c => c.DateTimeOffset(nullable: false, defaultValueSql: "CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"));
4.使用.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)方法
打完收工
另外
如其他數據庫時間戳類型映射模型時的類型不為byte[]時 都可以用此方法來解決
ef版本也不限於4.3.1 (沒有測試)
請其他使用高版本ef並且使用其他數據庫的TX 幫忙測試