实体框架7中的AddOrUpdate

Mat*_*ger 0 c# entity-framework

我正在尝试实现自己的,AddOrUpdate因为Entity Framework暂时不包含此功能.(我需要它)

我知道这里有类似的问题,但要么没有答案,要么是另一个问题.

所以,我在尝试实现更新部分时遇到困难.这是我的代码:

  • @this:我在数据库中输入的DbSet
  • 参数:在DB中检查是否输入的属性已存在
  • 条目:要添加或更新的所有条目

public static void AddOrUpdate<T>(this DbSet<T> @this, Func<T, object> parameter, params T[] entries) where T: class, IEntity
{
    IEnumerable<object> keysExisting = @this.Select(parameter);

    foreach (T entry in entries)
    {
        bool entryExistsAlready = keysExisting.Contains(parameter.Invoke(entry));
        if (!entryExistsAlready)
        {
            @this.Add(entry);
            return;
        }
        entry.Id = @this.First(w => parameter.Invoke(w).Equals(parameter.Invoke(entry))).Id;
        @this.Attach(entry);
        @this.Update(entry);
    }
}
Run Code Online (Sandbox Code Playgroud)

为了完成信息,这就是我调用方法的方法(已经有一个ApplicationUser存储在数据库中,电子邮件"test@test.de"):

db.ApplicationUsers.AddOrUpdate(s => s.Email,
        new ApplicationUser{Email="test@test.de", Attribute="modified attribute"}
        );
Run Code Online (Sandbox Code Playgroud)

我尝试附加条目而不附加.我总是得到以下异常(Attach()或者,当没有附加时,在Update():

InvalidOperationException:无法跟踪实体类型"ApplicationUser"的实例,因为已经跟踪了具有相同键的此类型的另一个实例.添加新实体时,对于大多数键类型,如果未设置任何键,则将创建唯一的临时键值(即,如果为键属性指定了其类型的默认值).如果要为新实体显式设置键值,请确保它们不会与现有实体或为其他新实体生成的临时值发生冲突.附加现有实体时,请确保只有一个具有给定键值的实体实例附加到上下文.

任何想法,我如何更新我的条目?

更新:

我已经尝试过反射,只是设置每个属性的所有值,但ApplicationUser例如具有Role不可写的属性.所以我的方法调用会丢失数据.

Col*_*lin 5

使用以下约定:如果构成实体主键的所有属性都具有默认值(0,null等),则实体为new,否则它已存在:

public TEntity AddOrUpdate<TEntity>(DbContext context, TEntity entity)
    where TEntity : class
{
    context.Entry(entity).State =
        context.KeyValuesFor(entity).All(IsDefaultValue)
            ? EntityState.Added
            : EntityState.Modified;

    return entity;
}

private static bool IsDefaultValue(object keyValue)
{
    return keyValue == null
           || (keyValue.GetType().IsValueType
               && Equals(Activator.CreateInstance(keyValue.GetType()), keyValue));
}
Run Code Online (Sandbox Code Playgroud)

参考:

https://blog.oneunicorn.com/2012/05/03/the-key-to-addorupdate/