日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql timestamp 并发_MySQL 实现 EF Code First TimeStamp/RowVersion 并发控制

發布時間:2023/12/2 数据库 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql timestamp 并发_MySQL 实现 EF Code First TimeStamp/RowVersion 并发控制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在將項目遷移到MySQL 5.6.10數據庫上時,遇到和遷移到PostgreSQL數據庫相同的一個問題,就是TimeStamp/RowVersion并發控制類型在非Microsoft SQL Server數據庫中的實現。

先上網搜索解決方案,找到Ak.Ini的博文http://www.cnblogs.com/akini/archive/2013/01/30/2882767.html,于是嘗試使用文中介紹的方法。

項目中有一個類要解決并發更新的問題,該類定義:

public classStock

{public int Id { get; set; }

[Required(ErrorMessageResourceName= "Generic_Required", ErrorMessageResourceType = typeof(ValidationMessage))]public Location Location { get; set; }

[Required(ErrorMessageResourceName= "Generic_Required", ErrorMessageResourceType = typeof(ValidationMessage))]public Part Part { get; set; }public Batch Batch { get; set; }

[Required(ErrorMessageResourceName= "Generic_Required", ErrorMessageResourceType = typeof(ValidationMessage))]public int Quantity { get; set; }

[Required(ErrorMessageResourceName= "Generic_Required", ErrorMessageResourceType = typeof(ValidationMessage))]public int UpdatedBy { get; set; }

[Required(ErrorMessageResourceName= "Generic_Required", ErrorMessageResourceType = typeof(ValidationMessage))]public DateTime UpdatedTime { get; set; }public DateTime RowVersion { get; set; }

}

其中最后一個屬性是用作并發控制的,MySqlMigrationSqlGenerator不允許byte[]類型上標記TimeStamp/RowVersion,這里使用DateTime類型。

這是EF生成的Stocks表定義:

> DESCkit.Stocks+ ---------- + --------- + --------- + -------- + ------------ + ---------- +

| Field | Type | Null | Key | Default | Extra |

+ ---------- + --------- + --------- + -------- + ------------ + ---------- +

| Id | int(11) | NO | PRI | | auto_increment |

| Quantity | int(11) | NO | | | |

| UpdatedBy | int(11) | NO | | | |

| UpdatedTime | datetime | NO | | | |

| RowVersion | datetime | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |

| Location_Id | int(11) | NO | MUL | | |

| Part_PartNo | varchar(50) | NO | MUL | | |

| Batch_BatchNo | varchar(50) | YES | MUL | | |

+ ---------- + --------- + --------- + -------- + ------------ + ---------- +

8 rows

然后在DbContext的構造器中加入下面修改DbModelBuilder的代碼:

protected override voidOnModelCreating(DbModelBuilder modelBuilder)

{

modelBuilder.Conventions.Remove();

modelBuilder.Conventions.Remove();

modelBuilder.Entity().Property(p =>p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

modelBuilder.Entity().Property(p =>p.RowVersion).IsConcurrencyToken().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

}

上面代碼中前兩行是為了禁用EF級聯刪除的特性,可以參考我以前的博文:http://www.cnblogs.com/jlzhou/archive/2012/03/13/2394333.html

后兩行顯式聲明Id屬性為自增類型,其實EF默認會將Id屬性設置為自增類型,但是在本例中,如果不顯式聲明,EF在生成數據庫時會莫名其妙的將Id屬性當作一般類型處理,不知道是不是因為最后一行設置RowVersion屬性為Identity造成的。

我編寫了一個小程序,用于顯式控制EF根據類定義生成數據庫,并且在生成數據庫后,使用執行SQL語句的方式,修改數據庫對象的定義,比如加入DEFAULT值或者添加索引等約束。下面是代碼片段:

//DbContext構造器中的部分代碼,通過isDoInitialize參數來控制是否初始化數據庫。

public BestDbContext(string databaseName, bool isDoInitialize = true) : base(databaseName)

{if (!isDoInitialize)

{

Database.SetInitializer(null);

}

}//初始化數據庫

Database.SetInitializer(new DropCreateDatabaseAlways());using (var db = new BestDbContext("name=" +databaseName))

{try{

db.Database.Initialize(force:false);

MessageBox.Show("Database initialized!");

}catch(Exception ex)

{

MessageBox.Show("Initialization Failed..." +ex.Message);

}stringsql;

sql= @"ALTER TABLE `kit`.`Stocks` CHANGE COLUMN `RowVersion` `RowVersion` DATETIME NOT NULL

DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ;";

db.Database.ExecuteSqlCommand(sql);

}

注意上面代碼最后的sql執行部分,這里加入對RowVersion數據庫服務器端的缺省值設置,自MySQL 5.6.5版本開始,DEFAULT CURRENT_TIMESTAMP 和 ON UPDATE CURRENT_TIMESTAMP 選項也可以應用到Datetime類型的列。

最后驗證上述方法,使用?Entity Framework Profiler 試用版(http://hibernatingrhinos.com/products/EFProf),下載解壓縮后,在Project引用中加入對HibernatingRhinos.Profiler.Appender.dll的引用,然后在應用的啟動代碼部分Application_Start in web applications,Program.Main in windows / console applications or the App constructor for WPF applications),加入這一行代碼:HibernatingRhinos.Profiler.Appender.EntityFramework.EntityFrameworkProfiler.Initialize();

啟動應用程序調試,并且啟動EFProf.exe監控程序,你就可以隨時看到EF動態生成的SQL命令了,很是方便,唯一的遺憾是這個工具是收費購買的,微軟又沒有提供非MSSQL的數據庫EF的SQL監控工具。

這是Stocks表在插入新記錄時,EF生成的SQL語句:

INSERT INTO`Stocks`

(`Quantity`,

`UpdatedBy`,

`UpdatedTime`,

`Location_Id`,

`Part_PartNo`,

`Batch_BatchNo`)VALUES ( 1,1,'2013-03-14T21:37:53' /*@gp1*/,1,'PART_A' /*@gp2*/,NULL);SELECT`Id`,

`RowVersion`FROM`Stocks`WHERE row_count() > 0

AND `Id` = last_insert_id()

可以看出,保存新對象實例到數據庫時,EF會從數據庫取回RowVersion的值,而這個值是數據庫那邊生成的。

這是更新Stocks表時,EF生成的SQL語句:

UPDATE`Stocks`SET `Quantity` = 6,

`UpdatedTime`= '2013-03-14T21:41:14' /*@gp1*/

WHERE (`Id` = 1)AND (`RowVersion` = '2013-03-14T21:14:25' /*@gp2*/)

可以看出,在更新對象實例到數據庫時,EF會從使用先前從數據庫取回RowVersion的值和主鍵作為條件來更新數據行,從而實現樂觀并發控制。

總結

以上是生活随笔為你收集整理的mysql timestamp 并发_MySQL 实现 EF Code First TimeStamp/RowVersion 并发控制的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。