Có hai giải pháp cho vấn đề này:
- Trong cửa sổ thuộc tính cho cột trong trình thiết kế EDMX, hãy thay đổi
StoreGeneratedPattern
trênPERIOD
cột (ValidFrom và ValidTo trong trường hợp của tôi) làidentity
. Danh tính tốt hơn được tính toán vì được tính toán sẽ khiến EF làm mới các giá trị trên một Chèn và Cập nhật thay vì chỉ một chèn cóidentity
- Tạo
IDbCommandTreeInterceptor
thực hiện để loại bỏ các cột thời kỳ. Đây là giải pháp ưa thích của tôi vì nó không yêu cầu phải thực hiện thêm khi thêm các bảng mới vào mô hình.
Đây là cách triển khai của tôi:
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;
}
}
Đăng ký bộ chặn này với EF bằng cách chạy phần sau ở bất kỳ đâu trong mã của bạn trước khi bạn sử dụng ngữ cảnh của mình:
DbInterception.Add(new TemporalTableCommandTreeInterceptor());