Get an Entity Framework Object anyway





4.00/5 (3 votes)
How to get an Entity Framework object - either from ObjectContext, from database or from scratch
In Entity Framework, you can get an Object from the ObjectContext[^] using GetObjectByKey[^] or TryGetObjectByKey[^]. When the object is not yet loaded into the
ObjectContext
, Entity Framework tries to get it from the database. But what if it doesn't even exist there? Take this:
public static TEntity GetObjectAnyway<TEntity>(this ObjectSet<TEntity> os, params object[] primaryKeyValues) where TEntity : EntityObject, new()
{
object oEntity;
TEntity entity;
var ek = os.CreateEntityKey(primaryKeyValues);
if (os.Context.TryGetObjectByKey(ek, out oEntity))
entity = (TEntity)oEntity;
else
{
entity = new TEntity { EntityKey = ek };
foreach (var v in ek.EntityKeyValues)
{
typeof(TEntity).InvokeMember(v.Key, BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty, null, entity, new[] { v.Value });
}
os.AddObject(entity);
}
return entity;
}
You'll need some helpers to make it work, here's the whole code:
using System.Data;
using System.Data.Objects;
using System.Data.Objects.DataClasses;
using System.Linq;
using System.Reflection;
using System.Data.Metadata.Edm;
namespace MyNamespace
{
public static class Extensions
{
public static EntityKey CreateEntityKey(this EntitySet es, params object[] primaryKeyValues)
{
var s = string.Format("{0}.{1}", es.EntityContainer.Name, es.Name);
var ien = primaryKeyValues.Select((o, i) => new EntityKeyMember(es.ElementType.KeyMembers[i].Name, o));
return new EntityKey(s, ien);
}
public static EntityKey CreateEntityKey<TEntity>(this ObjectSet<TEntity> os, params object[] primaryKeyValues) where TEntity : class
{
return os.EntitySet.CreateEntityKey(primaryKeyValues);
}
/// <summary>
/// Returns an object that has the specified primary key values from database or <see cref="ObjectContext"/>, even if it wasn't already existing.
/// </summary>
/// <remarks>
/// This method makes the following attempts, until it is able to return the object wanted.
/// <list type="number">
/// <item><description>
/// Try to get the object from the <see cref="ObjectContext"/>.
/// </description></item>
/// <item><description>
/// Try to get the object from the database.
/// </description></item>
/// <item><description>
/// Create a new object having the given <paramref name="primaryKeyValues"/>.
/// </description></item>
/// </list>
/// </remarks>
/// <typeparam name="TEntity">The type of the wanted object.</typeparam>
/// <param name="os">The <see cref="ObjectSet{T}"/> where the wanted object belongs to.</param>
/// <param name="primaryKeyValues">The values of the object's primary key in the order defined by the primary key.</param>
/// <returns>The object wanted.</returns>
public static TEntity GetObjectAnyway<TEntity>(this ObjectSet<TEntity> os, params object[] primaryKeyValues) where TEntity : EntityObject, new()
{
object oEntity;
TEntity entity;
var ek = os.CreateEntityKey(primaryKeyValues);
if (os.Context.TryGetObjectByKey(ek, out oEntity))
entity = (TEntity)oEntity;
else
{
entity = new TEntity { EntityKey = ek };
foreach (var v in ek.EntityKeyValues)
{
typeof(TEntity).InvokeMember(v.Key, BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty, null, entity, new[] { v.Value });
}
os.AddObject(entity);
}
return entity;
}
}
}