0

I am using .Net 4.5 and Entity Framework 6 to create a REST Web API. In my Update methods I need to attach the object recieved in the web api, back to the dbcontext. I have achieved this using the code below. What I want to do now, is to make this code reusable so that I can call AttachToContext for any object in the model.

I understand that I have to use generic type T and TEntity, but I cannot find any suitable examples.

//Repository.cs
public void UpdateOrderItem(OrderItem orderItem)
            {
                try
                {
                    AttachToContext(orderItem);
                    _context.SaveChanges();
                }
                catch (Exception e)
                {
                }
            }

            private void AttachToContext(OrderItem orderItem)
            {
                var entry = _context.Entry<OrderItem>(orderItem);
                if (entry.State == EntityState.Detached)
                {
                    var attachedEntity = FindExistingEntity(orderItem.Id);
                    if (EntityExists(attachedEntity))
                    {
                        UpdateEntityValues(attachedEntity, orderItem);
                    }
                    else
                    {
                        entry.State = EntityState.Modified;
                    }
                }

            }

            private OrderItem FindExistingEntity(int id)
            {
                var set = _context.Set<OrderItem>();
                return set.Find(id);
            }

            private void UpdateEntityValues(OrderItem existing, OrderItem updated)
            {
                var attachedEntry = _context.Entry(existing);
                attachedEntry.CurrentValues.SetValues(updated);
            }

            private bool EntityExists(object entity)
            {
                return entity != null;
            }
Yuliam Chandra
  • 14,494
  • 12
  • 52
  • 67
Karoline Brynildsen
  • 3,598
  • 6
  • 35
  • 45

1 Answers1

1

Your AttachToContext has dependency to primary key property, orderItem.Id, to change it into dynamic, you can introduce an interface and implement to all entities you have or just passing the id as parameters.

Interface

public interface IEntity
{
    public int Id { get; set; }
}
public class OrderItem : IEntity
{
    // body
}

Then modify the AttachToContext as follow.

private void AttachToContext<T>(T entity) where T : class, IEntity
{
    var entry = _context.Entry(entity);
    if (entry.State == EntityState.Detached)
    {
        var attachedEntity = FindExistingEntity<T>(entity.Id);
        if (EntityExists(attachedEntity))
        {
            UpdateEntityValues(attachedEntity, entity);
        }
        else
        {
            entry.State = EntityState.Modified;
        }
    }
}
private T FindExistingEntity<T>(int id) where T : class
{
    var set = _context.Set<T>();
    return set.Find(id);
}
private void UpdateEntityValues<T>(T existing, T updated) where T : class
{
    var attachedEntry = _context.Entry(existing);
    attachedEntry.CurrentValues.SetValues(updated);
}

The usage would be AttachToContext(orderItem);.

Passing The Keys

private void AttachToContext<T>(T entity, params object[] id) where T : class
{
    var entry = _context.Entry(entity);
    if (entry.State == EntityState.Detached)
    {
        var attachedEntity = FindExistingEntity<T>(id);
        if (EntityExists(attachedEntity))
        {
            UpdateEntityValues(attachedEntity, entity);
        }
        else
        {
            entry.State = EntityState.Modified;
        }
    }
}
private T FindExistingEntity<T>(object[] id) where T : class
{
    var set = _context.Set<T>();
    return set.Find(id);
}
private void UpdateEntityValues<T>(T existing, T updated) where T : class
{
    var attachedEntry = _context.Entry(existing);
    attachedEntry.CurrentValues.SetValues(updated);
}

The usage would be AttachToContext(orderItem, orderItem.Id);.

Another alternative would be using object set to get the primary key properties, then using reflection to get the value. To get the primary key properties has been explained in this post.

Community
  • 1
  • 1
Yuliam Chandra
  • 14,494
  • 12
  • 52
  • 67