Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I have a POCO, can I get a proxy from the DbContext?

I have a model that I get from a POST request. Since my view defines its POCO type, the object created from the submitted data is also a POCO. Being a POCO, it doesn't have various virtual properties overridden. Therefore, those virtual properties return null. This, in turn, means that I have to make separate queries based on the foreign keys to navigate through its properties (if I want to do anything more complex than just saving it).

Can I, given the POCO of my model, get the proxy that has all the overridden functionality?

(I had assumed that this is what db.Entry().Entity was for, but it still returns me the POCO object, not the proxy. I'm inspecting the runtime type of the object by mouse-over during breakpoint pauses.)

like image 668
Theodoros Chatzigiannakis Avatar asked Jun 18 '13 12:06

Theodoros Chatzigiannakis


1 Answers

Something along the lines of this code will do what you need. I've used automapper to copy values from the passed in entity to the proxied version.

The code checks whether the passed in entity is a proxy or not and handles it accordingly.

public class Repository<T> where T : class
{
    private readonly Context context;
    private bool mapCreated = false;
    public Repository(Context context)
    {
        this.context = context;
    }

    protected virtual T InsertOrUpdate(T e, int id)
    {
        T instance = context.Set<T>().Create();
        if (e.GetType().Equals(instance.GetType()))
            instance = e;
        else
        {
            if (!mapCreated)
            {
                Mapper.CreateMap(e.GetType(), instance.GetType());
                mapCreated = true;
            }
            instance = Mapper.Map(e, instance);
        }

        if (id == default(int))
            context.Set<T>().Add(instance);
        else
            context.Entry<T>(instance).State = EntityState.Modified;

        return instance;
    }
}

UPDATE version as described by @Colin in the comments that does not need automapper

public class Repository<T> where T : class
{
    private readonly Context context;
    public Repository(Context context)
    {
        this.context = context;
    }

    protected virtual T InsertOrUpdate(T e, int id)
    {
        T instance = context.Set<T>().Create();
        if (e.GetType().Equals(instance.GetType()))
        {
            instance = e;
        }
        else
        {
            DbEntityEntry<T> entry = context.Entry(instance);
            entry.CurrentValues.SetValues(e);
        }

        context.Entry<T>(instance).State =
            id == default(int)
                ? EntityState.Added
                : EntityState.Modified;

        return instance;
    }
}
like image 101
qujck Avatar answered Sep 21 '22 07:09

qujck