web-dev-qa-db-fra.com

quelle est la façon la plus raisonnable de savoir si une entité est attachée à dbContext ou non?

quand j'essaie d'attacher une entité au contexte, je reçois une exception

Un objet avec la même clé existe déjà dans ObjectStateManager. ObjectStateManager ne peut pas suivre plusieurs objets avec la même clé

Il s'agit d'un comportement attendu.

Mais je voudrais savoir comment ObjectStateManager sait cela? Je voudrais faire ce contrôle moi-même avant

55
maxlego

Si vous utilisez DbContext API (vous avez mentionné ef-code-first), vous pouvez simplement utiliser:

context.YourEntities.Local.Any(e => e.Id == id);

ou plus complexe

context.ChangeTracker.Entries<YourEntity>().Any(e => e.Entity.Id == id);

Dans le cas de l'API ObjectContext, vous pouvez utiliser:

context.ObjectStateManager.GetObjectStateEntries(~EntityState.Detached)
                          .Where(e => !e.IsRelationship)
                          .Select(e => e.Entity)
                          .OfType<YourEntity>()
                          .Any(x => x.Id == id);
75
Ladislav Mrnka

Voici une méthode d'extension pour extraire l'objet du contexte sans avoir à se soucier s'il est déjà attaché:

public static T GetLocalOrAttach<T>(this DbSet<T> collection, Func<T, bool> searchLocalQuery, Func<T> getAttachItem) where T : class
{
    T localEntity = collection.Local.FirstOrDefault(searchLocalQuery);

    if (localEntity == null)
    {
        localEntity = getAttachItem();
        collection.Attach(localEntity);
    }

    return localEntity;
}

Il suffit d'appeler:

UserProfile user = dbContext.UserProfiles.GetLocalOrAttach<UserProfile>(u => u.UserId == userId, () => new UserProfile { UserId = userId });
13
David Sherret

vérifier

entity.EntityState == System.Data.EntityState.Detached

avant de fixer

5
Kaido

Notez que si changement de suivi est désactivé sur votre contexte, demander au ObjectStateManager ou au ChangeTracker pourrait retourner que l'objet n'est pas dans le ObjectContext même s'il est en fait déjà là-dedans. Par conséquent, si vous essayez d'attacher un tel objet, il déclenchera une exception.

context.Set<T>.Local.Any(e => e.Id == id);

fonctionne si le suivi des modifications est désactivé.

si vous ne connaissez pas le type de l'objet, il existe différentes approches, soit vous définissez une méthode utilisant la réflexion ou d'autres techniques comme celle-ci int GetIdOf(object entity){...}

Ou vous définissez une interface utilisée par vos classes comme

public interface IMyEntity
{
    int Id{get;set;}
}

et utilisez-le de cette façon:

context.Set(e.GetType()).Local.Cast<IMyEntity>().Any(e => e.Id == id);
3
Dubbs777

vous pouvez interroger le dbContext avec la méthode d'extension "Any":

bool alreadyInDB = dbContext.Entity.Where(a=>a.ID==myEntity.id).Any();
0
Bongo Sharp