Error when inserting into temporal table using Entity Framework Core 2.1

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-06 04:13:21

Making the Period start column(SysStartTime) and Period end column(SysEndTime) should fix this issue. We can do this by

ALTER TABLE [dbo].[Department] ALTER COLUMN [SysStartTime] ADD HIDDEN;
ALTER TABLE [dbo].[Department] ALTER COLUMN [SysEndTime] ADD HIDDEN;

We can see the settings for hidden against these columns in the sys.columns table

SELECT * FROM sys.columns WHERE is_hidden = 1 

TL;DR:

  • Add entity.Property(e => e.Modified).HasComputedColumnSql("GENERATED ALWAYS AS ROW START"); for your "valid from" column in your OnModelCreating code.
  • You do not need to do anything for your "valid to" column.

Background:

I'm using .NET Core 2.2 with EntityFrameworkCore 3.0 Preview 6.

Rather than adding the HIDDEN attribute to those columns in @VPP's answer, I found that adding HasComputedColumnSql does the trick and it also means EF retrieves the column after each UPDATE.

Here's my CREATE TABLE:

CREATE TABLE [dbo].[Contacts] (
    [ContactId]             INT           NOT NULL IDENTITY, 
    [TenantId]              INT           NOT NULL, 
    [Created]               DATETIME2 (7)                               NOT NULL,
    [Modified]              DATETIME2 (7) GENERATED ALWAYS AS ROW START NOT NULL,
    [ValidTo]               DATETIME2 (7) GENERATED ALWAYS AS ROW END   NOT NULL CONSTRAINT [DF_Contacts_ValidTo] DEFAULT ('9999-12-31 23:59:59.9999999'),
    [Name]                  NVARCHAR(255) NOT NULL, 
    [PhoneNumber]           NVARCHAR(255) NOT NULL, 
    [HasAMulletHaircut]     BIT           NOT NULL, 
    [ListensToDevo]         BIT           NOT NULL, 
    [Status]                INT           NOT NULL, 

    CONSTRAINT PK_Contacts PRIMARY KEY ([ContactId], [TenantId]), 
    CONSTRAINT [FK_Contacts_Tenants] FOREIGN KEY ([TenantId]) REFERENCES dbo.Tenants( TenantId ),

    PERIOD FOR SYSTEM_TIME ([Modified], [ValidTo])
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE=[dbo].[Contacts_History], DATA_CONSISTENCY_CHECK=ON));

Here's what my Model Builder code looks like (originally generated by dotnet ef dbcontext scaffold, with my modifications labelled):

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Contact>(entity =>
        {
            entity.HasKey(e => new { e.ContactId, e.TenantId });

            // I added this:
            entity.Property(e => e.Modified).HasComputedColumnSql("GENERATED ALWAYS AS ROW START");
            // I added this, then commented it out because properties cannot have both `HasComputedColumnSql` and `HasDefaultValueSql`. But it works anyway.
            //entity.Property(e => e.ValidTo).HasComputedColumnSql("GENERATED ALWAYS AS ROW END");

            entity.Property(e => e.ValidTo).HasDefaultValueSql("('9999-12-31 23:59:59.9999999')");

            entity.HasOne(d => d.Tenant)
                .WithMany(p => p.Contacts)
                .HasForeignKey(d => d.TenantId)
                .OnDelete(DeleteBehavior.ClientSetNull)
                .HasConstraintName("FK_Contacts_Tenants");
        });

In short:

  • Add entity.Property(e => e.Modified).HasComputedColumnSql("GENERATED ALWAYS AS ROW START"); for your "valid from" column.
  • You do not need to do anything for your "valid to" column.

I ran tests and INSERT and UPDATE statements work fine (note that my code does not modify my "valid from" or "valid to" properties at all).

As mentioned above, the advantage of this approach is that after you call SaveChanges/SaveChangesAsync, EF will fetch the updated/new values for the "valid from" column automatically.

You can set the temporal date valid to/from columns to Is Hidden = True. Then EF does not care and your temporal version works without any extra work. When EF supports it (3.0ish) you should be able to use .FromSql($"SELECT * FROM dbo.Products FOR SYSTEM_TIME AS OF {{0}}", date.ToUniversalTime()) to filter that data but most front ends only care about the recent data so it might not be an issue for most of us.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!