sql >> Databasteknik >  >> RDS >> Sqlserver

Entity Framework fungerar inte med temporal tabell

Det finns två lösningar på detta problem:

  1. I egenskapsfönstret för kolumnen i EDMX-designern, ändra StoreGeneratedPattern under PERIOD kolumner (ValidFrom och ValidTo i mitt fall) för att vara identity . Identitet är bättre än beräknad eftersom computed kommer att få EF att uppdatera värdena på en infoga och uppdatera i motsats till bara en infogning med identity
  2. Skapa en IDbCommandTreeInterceptor implementering för att ta bort periodkolumnerna. Detta är min föredragna lösning eftersom det inte kräver något extra arbete när du lägger till nya tabeller till modellen.

Här är min implementering:

using System.Data.Entity.Infrastructure.Interception; 
using System.Data.Entity.Core.Common.CommandTrees; 
using System.Data.Entity.Core.Metadata.Edm; 
using System.Collections.ObjectModel;

internal class TemporalTableCommandTreeInterceptor : IDbCommandTreeInterceptor
{
    private static readonly List<string> _namesToIgnore = new List<string> { "ValidFrom", "ValidTo" };

    public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext)
    {
        if (interceptionContext.OriginalResult.DataSpace == DataSpace.SSpace)
        {
            var insertCommand = interceptionContext.Result as DbInsertCommandTree;
            if (insertCommand != null)
            {
                var newSetClauses = GenerateSetClauses(insertCommand.SetClauses);

                var newCommand = new DbInsertCommandTree(
                    insertCommand.MetadataWorkspace,
                    insertCommand.DataSpace,
                    insertCommand.Target,
                    newSetClauses,
                    insertCommand.Returning);

                interceptionContext.Result = newCommand;
            }

            var updateCommand = interceptionContext.Result as DbUpdateCommandTree;
            if (updateCommand != null)
            {
                var newSetClauses = GenerateSetClauses(updateCommand.SetClauses);

                var newCommand = new DbUpdateCommandTree(
                    updateCommand.MetadataWorkspace,
                    updateCommand.DataSpace,
                    updateCommand.Target,
                    updateCommand.Predicate,
                    newSetClauses,
                    updateCommand.Returning);

                interceptionContext.Result = newCommand;
            }
        }
    }

    private static ReadOnlyCollection<DbModificationClause> GenerateSetClauses(IList<DbModificationClause> modificationClauses)
    {
        var props = new List<DbModificationClause>(modificationClauses);
        props = props.Where(_ => !_namesToIgnore.Contains((((_ as DbSetClause)?.Property as DbPropertyExpression)?.Property as EdmProperty)?.Name)).ToList();

        var newSetClauses = new ReadOnlyCollection<DbModificationClause>(props);
        return newSetClauses;
    }
}

Registrera denna interceptor med EF genom att köra följande var som helst i din kod innan du använder ditt sammanhang:

DbInterception.Add(new TemporalTableCommandTreeInterceptor());


  1. Felkod:1822. Det gick inte att lägga till den främmande nyckeln. Saknar index för begränsning

  2. Lagrar effektivt 7 300 000 000 rader

  3. OM INTE FINNS i trigger

  4. PHP/MySQL-tidszonsförtydligande