In EF 4.0, se ho capito bene, ci sono due tipi di valori in Entity: valori correnti e valori originali.
Possiamo impostare i valori originali chiamando il metodo ApplyOriginalValues (TEntity) ma come ottenere i valori originali?Come ottenere i valori originali di un'entità in Entity Framework?
risposta
È possibile accedere attraverso ObjectStateEntry
var originalValues = context
.ObjectStateManager.GetObjectStateEntry(myEntity).OriginalValues;
@Eranga risposta è obsoleto per EF 5. Per qualche ragione, EF 5 non funziona bene quando ottenere valori originali utilizzando una dichiarazione come questa:
var originalValues = context.Entry(myEntity).OriginalValues;
la mia soluzione di lavoro utilizza AsNoTracking()
metodo dal DbSet
, come nell'esempio qui sotto:
var originalEntity = context.MyEntities.AsNoTracking().FirstOrDefault(me => me.MyEntityID == myEntity.MyEntityID);
AsNoTracking() prestazioni migliori pure - google it – Moji
Come ottenere solo i valori modificati ?? –
@AwaisMahmood Penso che questo meriti una domanda a parte. –
Questo potrebbe essere raffinato ulteriormente di seguito:
var originalEntity = context.MyEntities.AsNoTracking()
.FirstOrDefault(me => me.MyEntityID == myEntity.MyEntityID);
Il Where
in quanto sopra, bene, risposta non è necessaria.
Mi sono imbattuto in un problema simile e AsNoTracking non era un'opzione per la mia situazione, quindi mi è venuto in mente qualcosa che funzioni abbastanza bene per me: prima "clonare" l'entità, quindi apportare delle modifiche.
public T Clone<T>(T entity)
where T : class, new() {
var clone = new T();
var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy)
.Where(a => a.CanRead &&
a.CanWrite &&
a.GetMethod.IsFinal);
foreach (var property in properties) {
property.SetValue(clone, property.GetValue(entity));
}
return clone;
}
e quindi confrontare il clone con il modificato.
public string GenerateChangeText<T>(T original, T current)
where T : class, new() {
var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy)
.Where(a => a.CanRead &&
a.CanWrite &&
a.GetMethod.IsFinal);
var changes = string.Empty;
foreach (var property in properties) {
var originalValue = property.GetValue(original);
var currentValue = property.GetValue(current);
if (originalValue == null && currentValue == null) continue;
if ((originalValue != null && !originalValue.Equals(currentValue)) ||
(currentValue != null && !currentValue.Equals(originalValue))) {
changes += $" changed {property} from {original ?? "NULL"} to {current ?? "NULL"}.";
}
}
return changes;
}
Esistono alcune versioni di Entity Framework in uso.
Io stesso preferisco Codice Prima e con tale API è facile come
_context.Entry(Entity).Reload();
Gli API hanno un metodo di aggiornamento sul ObjectContext che può aiutare in alcuni casi d'uso
ObjectContext.Refresh(RefreshMode.StoreWins, Entity);
Docs https://msdn.microsoft.com/en-us/library/bb896255(v=vs.110).aspx
Questa risposta si riferisce a Entity Framework 6. In EF 6 c'è un valore originale e il valore corrente https://msdn.microsoft.com/en-us/library/gg679512(v=vs.113).aspx Dopo aver cercato e non aver trovato una buona risposta, mi è venuta in mente la seguente funzione di test e ho pensato di postarla per gli altri che dovevano fare il stesso.
private void test()
{
// table has a field Description of type varchar(200)
WDMDBEntities context = new WDMDBEntities();
var query = context.Brands;
List<Brand> records = query.ToList();
if (records.Count > 0)
{
Brand currentRecord = records[0];
currentRecord.Description = "some new text";
string originalValue = null;
switch (context.Entry(currentRecord).State)
{
case System.Data.Entity.EntityState.Added:
originalValue = null;
break;
case System.Data.Entity.EntityState.Deleted:
case System.Data.Entity.EntityState.Detached:
case System.Data.Entity.EntityState.Modified:
case System.Data.Entity.EntityState.Unchanged:
originalValue = context.Entry(currentRecord).Property(u => u.Description).OriginalValue;
break;
}
}
context.Dispose();
}
originalValues è il tipo DbDataRecord. Come convertirlo in tipo di entità? – JatSing
@Sun non ha tipi di entità. È necessario eseguire il cast dei valori sul tipo appropriato. es. 'var name = (stringa) originalValues [" Name "];' – Eranga