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();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
使用 Entity Framework CoreEF Core)进行数据库操作时,你不需要显式打开或关闭数据库连接。EF Core 会自动管理数据库连接的打开和关闭。 要使用 SQL 更新数据,你可以使用 EF Core 提供的 `ExecuteSqlRaw` 或 `ExecuteSqlInterpolated` 方法。这些方法允许你执行原始的 SQL 查询或命令。 下面是一个示例代码,展示了如何使用 EF Core 执行原始 SQL 更新数据: ```csharp using Microsoft.EntityFrameworkCore; using System; // 创建 DbContext 类 public class YourDbContext : DbContext { public YourDbContext(DbContextOptions<YourDbContext> options) : base(options) { } // DbSet 和其他属性... public DbSet<IPS_Invoice> IPS_Invoices { get; set; } } public class IPS_Invoice { public int IPS_ID { get; set; } public bool BLOCK { get; set; } public DateTime? BLOCKTIME { get; set; } } public class YourRepository { private readonly YourDbContext _dbContext; public YourRepository(YourDbContext dbContext) { _dbContext = dbContext; } public string UpdateBlockTime(IPS_Invoice model) { string message = ""; try { int affectedRows = _dbContext.Database.ExecuteSqlInterpolated($"UPDATE IPS_Invoices SET BLOCK = true, BLOCKTIME = {DateTime.Now} WHERE IPS_ID = {model.IPS_ID}"); if (affectedRows > 0) { message = "True"; } else { message = "No records updated"; } } catch (Exception e) { message = "False"; // 处理异常... } return message; } } ``` 在上述代码,我们首先创建了一个继承自 `DbContext` 的 `YourDbContext` 类,并定义了需要操作的实体类 `IPS_Invoice`。然后,我们创建了一个名为 `YourRepository` 的仓储类,在该类使用 `ExecuteSqlInterpolated` 方法执行原始的 SQL 更新操作。 在 `UpdateBlockTime` 方法,我们使用插值字符串(interpolated string)来构建 SQL 命令,并将其传递给 `ExecuteSqlInterpolated` 方法进行执行。如果更新操作成功影响了一行或多行数据,返回的 `affectedRows` 将大于 0。 请根据你的实际情况修改代码,并确保在使用 EF Core 时按照最佳实践进行数据库操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

枫杨NET

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

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

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

打赏作者

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

抵扣说明:

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

余额充值