【发布时间】:2016-09-01 21:36:42
【问题描述】:
我正在尝试实现我自己的AddOrUpdate,因为实体框架目前不包含此功能。 (我需要它)
我知道这里有类似的问题,但要么没有答案,要么是另一个问题。
所以,我在尝试实施更新部分时遇到了困难。这是我的代码:
- @this:我在数据库中的条目 DbSet
- 参数:在数据库中检查条目是否已存在的属性
- 条目:要添加或更新的所有条目
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);
}
}
为了完成信息,这就是我调用方法的方式(数据库中已经存储了一个 ApplicationUser,电子邮件为“test@test.de”):
db.ApplicationUsers.AddOrUpdate(s => s.Email,
new ApplicationUser{Email="test@test.de", Attribute="modified attribute"}
);
我尝试附加条目而不附加。我总是遇到以下异常(在Attach() 上,或者在不附加时,在Update() 上:
InvalidOperationException:无法跟踪实体类型“ApplicationUser”的实例,因为已经在跟踪具有相同键的该类型的另一个实例。添加新实体时,对于大多数键类型,如果没有设置键(即,如果键属性为其类型分配了默认值),则会创建一个唯一的临时键值。如果您为新实体显式设置键值,请确保它们不会与现有实体或为其他新实体生成的临时值发生冲突。附加现有实体时,请确保只有一个具有给定键值的实体实例附加到上下文。
任何想法,我可以如何更新我的条目?
更新:
我已经尝试过反射,只是设置每个属性的所有值,但是 ApplicationUser 例如具有不可写的属性Role。所以我会从我的方法调用中丢失数据。
【问题讨论】:
-
您可以从数据库中获取实体,然后将更改的属性从条目分配给该实体并尝试执行相同操作。
-
@divya 是的,但这是一种
Seed()-方法,我必须提供完整的对象。我并不总是知道哪些属性会发生变化。 -
那么您必须分配所有属性...请参考:entityframeworktutorial.net/EntityFramework4.3/…
-
@divya 这是通用的。我不知道该类,也不知道属性-您的链接显示了如何设置一个属性并将整个对象的状态设置为已修改。
AddOrUpdate接受任何对象,而不是类中的特定对象。我必须为每个班级写AddOrUpdate(),或者像深度克隆一样通过反射来完成。 -
我认为您可以使用反射遍历泛型类的每个属性,然后将每个属性分配给原始对象。
标签: c# entity-framework