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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

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

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

在將項(xiàng)目遷移到MySQL 5.6.10數(shù)據(jù)庫(kù)上時(shí),遇到和遷移到PostgreSQL數(shù)據(jù)庫(kù)相同的一個(gè)問(wèn)題,就是TimeStamp/RowVersion并發(fā)控制類型在非Microsoft SQL Server數(shù)據(jù)庫(kù)中的實(shí)現(xiàn)。

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

項(xiàng)目中有一個(gè)類要解決并發(fā)更新的問(wèn)題,該類定義:

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; }

}

其中最后一個(gè)屬性是用作并發(fā)控制的,MySqlMigrationSqlGenerator不允許byte[]類型上標(biāo)記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的構(gòu)造器中加入下面修改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級(jí)聯(lián)刪除的特性,可以參考我以前的博文:http://www.cnblogs.com/jlzhou/archive/2012/03/13/2394333.html

后兩行顯式聲明Id屬性為自增類型,其實(shí)EF默認(rèn)會(huì)將Id屬性設(shè)置為自增類型,但是在本例中,如果不顯式聲明,EF在生成數(shù)據(jù)庫(kù)時(shí)會(huì)莫名其妙的將Id屬性當(dāng)作一般類型處理,不知道是不是因?yàn)樽詈笠恍性O(shè)置RowVersion屬性為Identity造成的。

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

//DbContext構(gòu)造器中的部分代碼,通過(guò)isDoInitialize參數(shù)來(lái)控制是否初始化數(shù)據(jù)庫(kù)。

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

{if (!isDoInitialize)

{

Database.SetInitializer(null);

}

}//初始化數(shù)據(jù)庫(kù)

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執(zhí)行部分,這里加入對(duì)RowVersion數(shù)據(jù)庫(kù)服務(wù)器端的缺省值設(shè)置,自MySQL 5.6.5版本開始,DEFAULT CURRENT_TIMESTAMP 和 ON UPDATE CURRENT_TIMESTAMP 選項(xiàng)也可以應(yīng)用到Datetime類型的列。

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

啟動(dòng)應(yīng)用程序調(diào)試,并且啟動(dòng)EFProf.exe監(jiān)控程序,你就可以隨時(shí)看到EF動(dòng)態(tài)生成的SQL命令了,很是方便,唯一的遺憾是這個(gè)工具是收費(fèi)購(gòu)買的,微軟又沒(méi)有提供非MSSQL的數(shù)據(jù)庫(kù)EF的SQL監(jiān)控工具。

這是Stocks表在插入新記錄時(shí),EF生成的SQL語(yǔ)句:

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()

可以看出,保存新對(duì)象實(shí)例到數(shù)據(jù)庫(kù)時(shí),EF會(huì)從數(shù)據(jù)庫(kù)取回RowVersion的值,而這個(gè)值是數(shù)據(jù)庫(kù)那邊生成的。

這是更新Stocks表時(shí),EF生成的SQL語(yǔ)句:

UPDATE`Stocks`SET `Quantity` = 6,

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

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

可以看出,在更新對(duì)象實(shí)例到數(shù)據(jù)庫(kù)時(shí),EF會(huì)從使用先前從數(shù)據(jù)庫(kù)取回RowVersion的值和主鍵作為條件來(lái)更新數(shù)據(jù)行,從而實(shí)現(xiàn)樂(lè)觀并發(fā)控制。

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。