繁体   English   中英

C# Pomelo mySQL 触发器 onUpdate 时间戳

[英]C# Pomelo mySQL trigger onUpdate Timestamp

我试图在 Pomelo.MySQL 中创建一个日志表,它有一个 onUpdate 时间戳,但我似乎无法用实体框架触发它。

这是我的桌子模型

public class OrganisationLog
{
    [Key]
    public int Id { get; set; }

    [Column(TypeName = "VARCHAR(1024)")]
    [Required(AllowEmptyStrings = false)]
    public string MachineName { get; set; }

    [DefaultValue("CURRENT_TIMESTAMP")]
    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public DateTime LastContact { get; set; }

    public int OrganisationId { get; set; }

    [ForeignKey("OrganisationId")]
    public Organisation Organisation { get; set; }
}

下面是应该工作的功能。

private void UpdateOrganisationLog(Organisation organisation, string machineName)
{
    try
    {
        OrganisationLog organisationLog = _context.OrganisationLogs
            .Where(x => x.OrganisationId == organisation.Id && x.MachineName == machineName)
            .FirstOrDefault();

        if (organisationLog == null)
        {
            organisationLog = new OrganisationLog()
            {
                MachineName = machineName,
                OrganisationId = organisation.Id,
                LastContact = DateTime.Now
            };
            _context.OrganisationLogs.Add(organisationLog);
        }
        else
        {
            _context.Update(organisationLog);
        }
        _context.SaveChanges();
    }
    catch (Exception e)
    {
        Console.WriteLine("Error " + e.Message);
    }
}

我最终使用手动 SQL 语句使其工作,但我想通过实体框架弄清楚它。

_context.Database.ExecuteSqlCommand($"UPDATE organisationlogs SET LastContact = CURRENT_TIMESTAMP(6) WHERE Id = {organisationLog.Id}");

它可能与CURRENT_TIMESTAMP(6)而不是CURRENT_TIMESTAMP()吗? 不知道为什么 Entity Framework 将其设为(6)

根据默认值上的 EF Core 文档,不支持数据注释:

您不能使用数据注释设置默认值。

如果 EF Core 支持它,那么将它用于CURRENT_TIMESTAMP可能仍然无效,因为它不是System.DateTime值,而是技术上的 SQL 片段。


在您的情况下,使用.HasDefaultValueSql()指定 SQL 片段的如下 FluentAPI 配置应该适用于 Pomelo 3.0.1+:

class MyContext : DbContext
{
    // ...

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<OrganisationLog>(entity =>
        {
            entity.Property(e => e.LastContact)
                .HasDefaultValueSql("CURRENT_TIMESTAMP");
        });
    }
}

DatabaseGenerated(DatabaseGeneratedOption.Computed)属性应该不是必需的。


如果您希望值不仅在创建时生成,而且在更改表行时自动更新,请改用以下模型定义:

class MyContext : DbContext
{
    // ...

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<OrganisationLog>(entity =>
        {
            entity.Property(e => e.LastContact)
                .ValueGeneratedOnAddOrUpdate();
        });
    }
}

如果您只想在更改表行时更新值,而不是在创建它时更新值,您可以将ValueGeneratedOnUpdate()与 EF Core 3.1.0 一起使用。

EF Core < 3.1.0 中存在一个错误,其中ValueGeneratedOnUpdate()不会生成正确的 C# 代码。 对于大多数人来说,这应该不是问题,因为对 EF Core 3.0.0 的终生支持无论如何都非常有限(并且如上所述,自 3.0.1 以来,该功能仅由 Pomelo 支持)。 如果您无论如何都需要 3.0.1 >= Pomelo < 3.1.0 的解决方法,那么使用ValueGeneratedOnAddOrUpdate()将适用于大多数用例。


请参阅我们的 GitHub 存储库上的#959 ,以获取与CURRENT_TIMESTAMP结合实现对datetime列的支持的修复程序以及更多详细信息。


我正在使用Pomelo.EntityFramework.MySql版本2.1.4 我用 Elastic Beanstalk 托管它,所以我需要使用旧版本的 dotnet

对于 Pomelo 2.1.4以上所有内容都无法正常工作(使用timestamptimestamp(6)可能有效,但您需要手动更改DEFAULT语句以删除单引号,以防您为数据库搭建脚手架)。 但是您始终可以更改表定义作为解决方法。

如果您正在使用迁移,则可以将以下行(或类似内容)添加到Up()方法中,例如:

migrationBuilder.Sql("ALTER TABLE `OrganisationLog` CHANGE COLUMN `LastContact` datetime(6) CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;");

不理想,但它应该适用于较旧的 Pomelo 版本。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM