我有一个大型模型,它已经通过反序列化进行了部分更新。由于它只是部分更新,所以当我将其传递给实体框架更新时,我想忽略任何空值。最终EntityState.Modified
已设置,但我遇到的问题是所有字段都已更新。这意味着任何现在空白的东西现在都在数据库中消隐。
是否可以通过设置更改此默认行为或覆盖检查null的方法?看起来,由于上下文期望完整的模型,我不能简单地设置一些值。
我已经通过映射验证了这一点,只有我需要修改和发生相同的行为。忽略上下文更新中的空值
1
A
回答
0
这是一个有点乏味的问题,我不得不解决。因为缺乏更直接的解决方案,最终我决定不想尝试像EF的SaveChanges-and-the-likes这样被调用的下游解决问题(即不需要“挂钩到“EF太晚了),而是尽可能高的上游/尽可能早 -
也就是说,这样做后,我得到一个令人满意的反序列化,这是有意义的变种模型,每个实体(在我的用例中,没有可更新的属性代表关系,但只有独立的属性,在E/R说法 - YMMV)
所以,我选择了“填充”助手,沿着:
static void Populate(object from, object to)
{
var sourceType = from.GetType();
foreach (PropertyInfo target in to.GetType().GetProperties())
{
// Is the property at the target object writable and *not* marked
// as `[NotMapped]'?
var isUpdatable =
target.CanWrite &&
(target.GetCustomAttribute<NotMappedAttribute>(true) == null);
if (isUpdatable)
{
// If so, just find the corresp. property with the same name at the source object
// (caller is assumed responsible to guarantee that there is one, and of the same type, here)
var source = sourceType.GetProperty(target.Name);
var @default = sourceType.IsValueType ? Activator.CreateInstance(sourceType) : null;
var equality = (IEqualityComparer)typeof(EqualityComparer<>).MakeGenericType(sourceType).GetProperty("Default", BindingFlags.Public | BindingFlags.Static).GetValue(null);
var value = source.GetValue(from);
// Test for <property value> != default(<property type>)
// (as we don't want to lose information on the target because of a "null" (or "default(...)") coming from the source)
if (!equality.Equals(value, @default))
{
target.SetValue(to, value, null);
}
}
}
}
其中“从”是刚刚部分以任何反串行化代码填充新鲜实体实例,并在“到”是住在的DbContext(可以是一个EF代理或不)的实际目标实体;
其中NotMappedAttribute是EF的平常。
您通常会在完成“from”实例的反序列化(& /或DTO映射)之后调用Populate,但无论如何,在SaveChanges()获取对DbContext的所有“到“实体 - 显然,我们假设有一个可行的1:1映射”,从“...”到“,Populate的调用者知道/可以弄清楚。
注意我仍然不知道是否有一种更优雅(更直接)的方式来做到这一点,而无需借助反射 - 所以,FWIW。上面的代码
备注
1)可(或应当)可以以各种方式作出更多的防御,这取决于主叫方假设; 2)人们可能想要缓存那些IEqualityComparer的(& /或PropertyInfo的)无论(好)的原因可能会出现 - 在我的情况下,我不需要;
3)最后,我的理解是,第三方librairies如AutoMapper还专门为这一类任务的设计,如果你能承受的额外依赖
“HTH,
相关问题
- 1. C++值更新/忽略
- 2. Jboss.xml忽略上下文根
- 3. BeanUtils.copyProperties忽略空值
- 4. JavaScript忽略空白下拉值
- 5. 使用laravl5忽略更新时的空表单值
- 6. str.match忽略空白值
- 7. Linq搜索,忽略空值
- 8. accepts_nested_attributes_for忽略空白值
- 9. Kotlin - Jackson忽略空值
- 10. ef6是否忽略列中的空值?
- 11. 如何忽略R中的空值?
- 12. 忽略python中的空值列
- 13. DataContractSerializer - 忽略数组中的空值
- 14. 忽略MYSQL查询中的空值
- 15. 忽略PHP/MySQL中multipe下拉列表的空值
- 16. ASP.NET文本框忽略更新面板
- 17. SVN:忽略文件/文件夹上更新
- 18. SolrJ:忽略更新中的字段
- 19. 忽略回文中的空白
- 20. 忽略文本字段中的空白
- 21. SQL Server 2008中 - 忽略空值
- 22. Subversion svn:忽略更新
- 23. 忽略更新形式
- 24. Svn忽略版本更新
- 25. 忽略perl中的空行?
- 26. R - 忽略空?
- 27. 忽略用户忽略的应用程序更新
- 28. Json.net忽略子对象的空值
- 29. 更新()函数在mongo中忽略limit()
- 30. 检查空列值的情况下,并忽略它们
我有什么非常相似,我创建了一个映射工厂,负责映射基础架构的各个层次(例如API-> Business-> Data)。我很欣赏Reflection对你来说不是一个好选择。我认为这种情况也不合理。另外,我的工作组审查了AutoMapper,但由于其他原因拒绝了它。感谢您的反馈。 – McArthey
'不错,除了使用像AutoMapper或反射之类的东西外,我希望自己找到了一些不需要入侵EF的东西,但是仍然是上面的帮助者在我的情况下完成了这项工作。无论如何,我确信它可以用于中央,易于重构的位置(我需要以不同的方式做)。 – YSharp
经过审查这个代码效果很好(减去几个空检查),但也许我误解了一些东西?我映射到数据库的结果模型(在这种情况下为'to')仍然包含反射后模型的所有映射属性,这意味着空值在数据层仍然会导致问题。最终,我需要删除包含空值的所有属性。 – McArthey