实体框架不使用时态表

Mat*_*uwe 14 c# sql-server temporal-database entity-framework-6 sql-server-2016

我正在使用数据库第一实体框架6.在将我的模式中的一些表更改为临时表后,我在尝试插入新数据时开始收到以下错误:

Cannot insert an explicit value into a GENERATED ALWAYS column in table '<MyDatabase>.dbo.<MyTableName>. Use INSERT with a column list to exclude the GENERATED ALWAYS column, or insert a DEFAULT into GENERATED ALWAYS column.

看起来EF正在尝试更新PERIOD由系统管理的列的值.

从EDMX文件中删除列似乎可以解决问题,但这不是一个可行的解决方案,因为每次从数据库重新生成模型时都会重新添加列.

Mat*_*uwe 19

这个问题有两种解决方案:

  1. 在在EDMX设计师的列的属性窗口,将StoreGeneratedPatternPERIOD列(ValidFrom和ValidTo在我的情况)是两种identityidentity.标识可能更好,因为计算将导致EF刷新插入和更新上的值,而不是只插入插入IDbCommandTreeInterceptor
  2. 创建一个StoreGeneratedPattern实现以删除期间列.这是我的首选解决方案,因为在向模型添加新表时不需要额外的工作.

这是我的实现:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

在使用上下文之前,通过在代码中的任何位置运行以下命令来向EF注册此拦截器:

DbInterception.Add(new TemporalTableCommandTreeInterceptor());
Run Code Online (Sandbox Code Playgroud)

  • @AramGevorgyan - 您可以在属性上使用属性 [DatabaseGenerated(DatabaseGeneratedOption.Computed)] 或使用 Fluent API 方法 .ValueGeneratedOnAddOrUpdate() 例如 entity.Property(e =&gt; e.ValidFrom).ValueGeneratedOnAddOrUpdate(); [参见此处](http://www.learnentityframeworkcore.com/configuration/data-annotation-attributes/databasegenerated-attribute) 以供参考。 (3认同)
  • 像魅力一样工作!`usings` 如下 `using System.Data.Entity.Infrastructure.Interception; 使用 System.Data.Entity.Core.Common.CommandTrees; 使用 System.Data.Entity.Core.Metadata.Edm; 使用 System.Collections.ObjectModel;` (2认同)

iho*_*ond 7

我在系统版本表上遇到了这个错误,我只是将 EF 配置设置为忽略系统维护的列,就像这样

            Ignore(x => x.SysEndTime);
            Ignore(x => x.SysStartTime);
Run Code Online (Sandbox Code Playgroud)

和插入/更新与数据库一起工作,仍然根据需要更新这些列以保留历史记录。另一种方法是像这样设置列

Property(x => x.SysEndTime).IsRequired().HasColumnType("datetime2").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);
Run Code Online (Sandbox Code Playgroud)