Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Entity Framework не работи с времева таблица

Има две решения на този проблем:

  1. В прозореца на свойствата за колоната в EDMX дизайнера променете StoreGeneratedPattern на PERIOD колони (ValidFrom и ValidTo в моя случай) да бъдат identity . Идентичността е по-добра от изчислената, тъй като изчислената ще накара EF да опресни стойностите при вмъкване и актуализиране, за разлика от просто вмъкване с identity
  2. Създайте IDbCommandTreeInterceptor изпълнение за премахване на колоните за период. Това е моето предпочитано решение, тъй като не изисква допълнителна работа при добавяне на нови таблици към модела.

Ето моята реализация:

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;
    }
}

Регистрирайте този прехващач с EF, като изпълните следното навсякъде в кода си, преди да използвате своя контекст:

DbInterception.Add(new TemporalTableCommandTreeInterceptor());


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Само един израз може да бъде посочен в списъка за избор, когато подзаявката не е въведена с EXISTS

  2. Как да ограничите редовете в набор от резултати на SQL Server

  3. Не може да се зареди насипно. Код за грешка в операционната система 5 (Достъпът е отказан.)

  4. Вземете краткото име в SQL Server (T-SQL)

  5. 🆕 SQL Server 2022 Първи поглед - Топ 5 нови функции (Бонус 5 функции)