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
.
You could use:
var objContext = ((IObjectContextAdapter)context).ObjectContext;
var objSet = objContext.CreateObjectSet<TEntity>();
var entityKey = objContext.CreateEntityKey(objSet.EntitySet.Name, entity);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With