針對Mysql 使用EF Code First時 TimeStamp/RowVersion 類型 的解決辦法


環境:

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 幫忙測試


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM