इस समस्या के दो समाधान हैं:
- EDMX डिज़ाइनर में कॉलम के लिए प्रॉपर्टी विंडो में,
StoreGeneratedPattern
बदलेंPERIOD
. पर कॉलम (ValidFrom और ValidTo मेरे मामले में) होने के लिएidentity
. गणना की तुलना में पहचान बेहतर है क्योंकि गणना के कारण EF एक इंसर्ट और अपडेट पर मानों को रीफ्रेश करेगा, जैसा किidentity
के साथ केवल एक इंसर्ट के विपरीत है - एक
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());