There are two solutions to this problem:
- In the properties window for the column in the EDMX constructor, replace
StoreGeneratedPattern on the PERIOD columns (in my case ValidFrom and ValidTo) with identity . A certificate is better than a calculated one, since a computed one will force EF to update the values in Insert and Update, and not just in the insert with identity - Create an implementation of
IDbCommandTreeInterceptor to remove period columns. This is my preferred solution, as it does not require additional work when adding new tables to the model.
Here is my implementation:
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; } }
Register this interceptor with EF by doing the following anywhere in your code before using context:
DbInterception.Add(new TemporalTableCommandTreeInterceptor());
Matt ruwe
source share