Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Look up locally cached entity by key in EF 6 / Code First

EF 6, Code First

I am looking to write a TryGetLocalEntity() method for EF 6 DbContext that will lookup an entity by key and return it if it exists in DbContext.Set<TEntity().Local. I want to do the lookup based on entity key and not object reference.

So the method signature might be:

    public static bool TryGetLocalEntity<TContext, TEntity>(this TContext context, TEntity entity, out TEntity cachedEntity)
        where TContext : DbContext
        where TEntity : class
    {

        EntityKey key = ???GetEntityKey???(entity);
        cachedEntity = context.Set<TEntity>().Local.Where(e => ???).FirstOrDefault();
        return cachedEntity != null;
    }

The purpose for this is to take an entity that has been deserialized from another source and either 1) Attach() it to the DbContext if it doesn't exist locally (determined by entity key and not object reference) or 2) retrieve the locally cached entity if it does exist (again determined by entity key and not object reference). I know I can just get it from the DB, but I'd like to avoid the round-trip if I already have what I need.

The main step I think I am missing is creating an EntityKey from a detached POCO entity. From here, I think I can figure out how to look up in the DbContext based on EntityKey.

UPDATE Here's a crack at it. Obviously some hacks, and I haven't tested it yet:

using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Core;
using System.Data.Entity.Core.Objects;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Infrastructure.Pluralization;

    public static bool TryGetLocalEntity<TContext, TEntity>(this TContext context, TEntity entity, out TEntity cachedEntity)
        where TContext : DbContext
        where TEntity : class
    {
        EnglishPluralizationService pluralizationService = new EnglishPluralizationService();
        string setName = pluralizationService.Pluralize(typeof(TEntity).Name);
        ObjectContext objectContext = ((IObjectContextAdapter)context).ObjectContext;
        EntityKey key = objectContext.CreateEntityKey(setName, entity);
        try
        {
            cachedEntity = objectContext.GetObjectByKey(key) as TEntity;
        }
        catch (ObjectNotFoundException)
        {
            cachedEntity = null;
        }
        return cachedEntity != null;
    }

UPDATE What I have seems to work except when an entity exists in the context but hasn't been saved to the database yet. I've been digging around in the EF source trying to determine if an unsaved/added entity doesn't have an EntityKey.

like image 808
MikeJansen Avatar asked Sep 05 '25 03:09

MikeJansen


1 Answers

You could use:

var objContext = ((IObjectContextAdapter)context).ObjectContext;
var objSet = objContext.CreateObjectSet<TEntity>();
var entityKey = objContext.CreateEntityKey(objSet.EntitySet.Name, entity);
  • https://msdn.microsoft.com/en-us/library/system.data.entity.core.objects.objectcontext.createentitykey%28v=vs.113%29.aspx
  • Generic Way to Check If Entity Exists In Entity Framework?
like image 120
jjj Avatar answered Sep 08 '25 19:09

jjj