EF Core在SQL Server里的timestamp数据类型转移到Mysql中怎么使用

1.SQL Server里的timestamp数据类型

SQL Server 中的timestamp类型,不需要sql脚本中写入,更新数据时,数据库里会自己更新;该数据类型主要用于处理并发导致的数据覆盖。

参考文档:SQL Server数据库(时间戳timestamp)类型 (转载) - PowerCoder - 博客园 (cnblogs.com)

INSERT People([ID], [Name])
VALUES('2023042413400010', '小贱贱')

在这里插入图片描述

2.使用EF Core 写数据到数据库中,如果Timestamp数据类型不加Timestamp标签,会写入数据库失败;在Timestamp数据类型的字段上添加[DatabaseGenerated(DatabaseGeneratedOption.Computed)]标签也能写入成功;

​ 疑问:对于sql server数据库 Timestamp数据类型的字段,是应该加[Timestamp]标签还是[DatabaseGenerated(DatabaseGeneratedOption.Computed)]标签?

​ 对于使用[DatabaseGenerated(DatabaseGeneratedOption.Computed)]标签写入数据库不会失败的原因如下:
在这里插入图片描述

​ 言外之意就是使用[DatabaseGenerated(DatabaseGeneratedOption.Computed)]标签的字段,EF Core生成SQL语句的时候Insert时不会生成该字段;

通过第5点的测试得出结论,EF Core 配合 SQL SERVER数据库使用时,Timestamp数据类型的字段应该配合[Timestamp]标签使用。

3.使用原生EF 更新数据时,更新字段里没有VerNo字段,但VerNo字段仍会自动更新;
4.使用EF Core 7.0中的ExecuteUpdate更新数据,更新字段里没有VerNo字段,但VerNo字段仍会自动更新;

5.观察更新数据时的sql语句

SaveChanges()更新数据ExecuteUpdate方法更新数据
使用Timestamp标签SET NOCOUNT ON;
UPDATE [People] SET [Name] = @p0
OUTPUT INSERTED.[VerNo]
WHERE [ID] = @p1 AND [VerNo] IS NULL;
‘,N’@p1 varchar(50),@p0 varchar(50),@p2 varbinary(8)',@p1=‘2023042413400010’,@p0=‘钢铁小贱贱’,@p2=NULL

更新时因为Entity中没有给VerNo赋值,导致更新失败
exec sp_executesql N’UPDATE [p]
SET [p].[Name] = @__name_1
FROM [People] AS [p]
WHERE [p].[ID] = @__id_0’,N’@__name_1 varchar(50),@__id_0 varchar(50)',@__name_1=‘AI小贱贱’,@__id_0=‘2023042413400010’

执行成功,生成的sql脚本中没有VerNo字段,但VerNo字段在数据库中已经自动更新
使用[DatabaseGenerated(DatabaseGeneratedOption.Computed)]标签exec sp_executesql N’SET IMPLICIT_TRANSACTIONS OFF;
SET NOCOUNT ON;
UPDATE [People] SET [Name] = @p0
OUTPUT INSERTED.[VerNo]
WHERE [ID] = @p1;
‘,N’@p1 varchar(50),@p0 varchar(50)',@p1=‘2023042413400010’,@p0=‘源计划小贱贱’

更新数据成功,生成的SQL脚本里VerNo没有在Where条件里,只是更新成功后把VerNo输出出来
exec sp_executesql N’UPDATE [p]
SET [p].[Name] = @__name_1
FROM [People] AS [p]
WHERE [p].[ID] = @__id_0’,N’@__name_1 varchar(50),@__id_0 varchar(50)',@__name_1=‘钢铁军团小贱贱’,@__id_0=‘2023042413400010’

执行成功,生成的SQL语句中没有VerNo字段
不使用上述两种标签exec sp_executesql N’SET IMPLICIT_TRANSACTIONS OFF;
SET NOCOUNT ON;
UPDATE [People] SET [Name] = @p0
OUTPUT 1
WHERE [ID] = @p1;
‘,N’@p1 varchar(50),@p0 varchar(50)',@p1=‘2023042413400010’,@p0=‘幻灵战队小贱贱’

更新数据成功,生成的SQL脚本里没有VerNo
exec sp_executesql N’UPDATE [p]
SET [p].[Name] = @__name_1
FROM [People] AS [p]
WHERE [p].[ID] = @__id_0’,N’@__name_1 varchar(50),@__id_0 varchar(50)',@__name_1=‘源计划小贱贱’,@__id_0=‘2023042413400010’

更新数据成功,生成的SQL脚本里没有VerNo

在SQL Server中Timestamp主要是用来处理并发冲突,所以在更新的时候最好是把VerNo查出来之后再进行更新。

使用[DatabaseGenerated(DatabaseGeneratedOption.Computed)]标签虽然能够更新成功,但是并不成处理并发冲突的问题。

2.Mysql中自定义一个防止并发冲突的字段

Mysql中的Timestamp数据类型只是单纯的一个时间戳类型,没有防止并发冲突的作用;如果想实现SQL Server里的Timestamp数据类型需要自定义一个并发冲突字段,并通过重写EF Core中的SaveChanges方法进行实现

1、Entity里声明并发冲突字段:

声明自定义并发冲突字段后,在更新时where条件里会带上该字段,与TimeStamp效果类似。

在Entity里使用[ConcurrencyCheck]标签标示或者使用Fluent API中使用IsConcurrencyToken方法。
public class Person
{
        public int PersonId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    	[ConcurrencyCheck]
        public byte[] RowVersion { get; set; }
}

modelBuilder.Entity<Person>().Property(p => p.RowVersion).IsConcurrencyToken();

2、重写savechanges,在SaveChanges方法里自动更新RowVer字段

public override int SaveChanges()
{
	this.ChangeTracker.DetectChanges();
	var modifiedEntities = this.ChangeTracker
        .Entries()
        .Where(x => x.State == EntityState.Modified || x.State == EntityState.Added)
        .Select(x => x.Entity)
        .ToList();
        foreach (var entity in modifiedEntities)
        {
            //给自定义的并发冲突字段赋值
            entity?.GetType().GetProperty("RowVer")
            ?.SetValue(entity, Encoding.Default.GetBytes(Guid.NewGuid().ToString()));
        }
        return base.SaveChanges();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枫杨NET

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值