动态地将条目附加到上下文

时间:2014-08-11 09:03:09

标签: asp.net entity-framework-6 dbcontext

我正在使用.Net 4.5和Entity Framework 6来创建REST Web API。 在我的Update方法中,我需要将在web api中收到的对象附加到dbcontext。我使用下面的代码实现了这一点。我现在要做的是使这段代码可以重用,这样我就可以为模型中的任何对象调用AttachToContext。

我知道我必须使用泛型类型T和TEntity,但我找不到任何合适的例子。

//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;
            }

1 个答案:

答案 0 :(得分:1)

您的AttachToContext依赖于主键属性orderItem.Id,将其更改为动态,您可以为所有实体引入接口和实现,或者只将id作为参数传递。

<强>接口

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

然后修改AttachToContext,如下所示。

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);
}

用法为AttachToContext(orderItem);

传递密钥

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);
}

用法为AttachToContext(orderItem, orderItem.Id);

另一种方法是使用对象集来获取主键属性,然后使用反射来获取值。 this post已解释了获取主键属性的问题。