2016-01-23 14 views
5

Come combinare Find() con AsNoTracking() quando si eseguono query su un contesto EF per impedire che l'oggetto restituito venga tracciato. Questo è ciò che io non posso fareCome combinare Find() e AsNoTracking()?

_context.Set<Entity>().AsNoTracking().Find(id); 

Come posso fare questo? Utilizzo la versione EF 6.

Nota: non desidero utilizzare SingleOrDefault() o Where. Non posso proprio perché il parametro Id è generico ed è un struct e non posso applicare l'operatore == per i generici in quel caso.

+0

"* posso proprio 't * "non è un'affermazione esecutiva a meno che tu non possa mostrarci il motivo per cui non puoi. Data la conoscenza della comunità SO, forse puoi, semplicemente non sai ** come **. – Tommy

+1

@ Grazie Tommy, ha aggiunto ulteriori dettagli. –

+0

Dovresti essere in grado di usare 'Equals' piuttosto che usare' == 'se questo è il tuo unico problema, ma sospetto che ci saranno anche altri problemi che non stai ancora condividendo nella tua domanda: non esiste un modo standard per estrarre le proprietà chiave di un'entità, ad esempio. – hvd

risposta

6

Così, invece di usando AsNoTracking() quello che puoi fare è Find() e poi staccarlo dal contesto. Credo che questo ti dia lo stesso risultato di AsNoTracking(), oltre all'overhead aggiuntivo di ottenere l'entità tracciata. Vedere EntityState per ulteriori informazioni.

var entity = Context.Set<T>().Find(id); 
Context.Entry(entity).State = EntityState.Detached; 
return entity; 
4
<context>.<Entity>.AsNoTracking().Where(s => s.Id == id); 

Find() non ha senso con AsNoTracking() perché Find si suppone che sia in grado di restituire le entità cingolati senza andare alla banca dati .. l'unica opzione con AsNoTracking è o Where o First o Single...

+1

Non posso usarlo, perché l'ID è generico e non posso usare l'operatore '==' con i generici :) –

+0

@HeidelBerGensis Can mostri il tuo intero snippet di codice perché il generico non può funzionare in questo caso? –

+1

controllare [questo post] (http://stackoverflow.com/questions/390900/cant-operator-be-applied-to-generic-types-in-c), per me il TKey è di tipo struct. Quindi, io non posso. –

0

Beh, credo che se si vuole veramente fare questo, si può provare a creare la tua espressione da soli. Presumo che tu abbia una classe di entità di base che è generica ed è da lì che proviene la proprietà della chiave generica. Ho chiamato questa classe KeyedEntityBase<TKey>, TKey è il tipo di chiave (se non si dispone di una classe, va bene, l'unica cosa che ho usato è il vincolo generico). Quindi è possibile creare un metodo di estensione come questo per costruire l'espressione da soli:

public static class Extensions 
{ 
    public static IQueryable<TEntity> WhereIdEquals<TEntity, TKey>(
      this IQueryable<TEntity> source, 
      Expression<Func<TEntity, TKey>> keyExpression, 
      TKey otherKeyValue) 
      where TEntity : KeyedEntityBase<TKey> 
    { 
    var memberExpression = (MemberExpression)keyExpression.Body; 
    var parameter = Expression.Parameter(typeof(TEntity), "x"); 
    var property = Expression.Property(parameter, memberExpression.Member.Name); 
    var equal = Expression.Equal(property, Expression.Constant(otherKeyValue)); 
    var lambda = Expression.Lambda<Func<TEntity, bool>>(equal, parameter); 
    return source.Where(lambda); 
    } 
} 

E poi, è possibile utilizzarlo come questo (per un tipo di chiave intera):

context.Set<MyEntity>.AsNoTracking().WhereIdEquals(m=>m.Id, 9).ToList();