EF DbSet.Find() 返回分离实体
Posted
技术标签:
【中文标题】EF DbSet.Find() 返回分离实体【英文标题】:EF DbSet.Find() returns Detached Entity 【发布时间】:2015-04-17 14:50:03 【问题描述】:我有一个非常简单的Entity
,只有 4 个字段:姓名、州、城市和 ID 以及一些验证。
[Table("Places")]
public class Place : BindableBase, IDataErrorInfo
private string name;
private string city;
private Estado state;
private int id;
[Required]
[StringLength(500)]
public string Name
get return this.name;
set SetProperty(ref name, value);
[Required]
[StringLength(500)]
public string City
get return this.city;
set SetProperty(ref city, value);
[Required]
public State State
get return this.state;
set SetProperty(ref state, value);
[Key]
public int Id
get return this.id;
set SetProperty(ref id, value);
[NotMapped]
public bool IsValid
get
return Validator.TryValidateObject(this, new ValidationContext(this), new Collection<ValidationResult>(), true);
#region IDataErrorInfo Members
/// <summary>
/// IDataErrorInfo Interface Error Message for the object.
/// </summary>
[NotMapped]
public string Error
get throw new NotImplementedException();
public string this[string propertyName]
get
var context = new ValidationContext(this)
MemberName = propertyName
;
var results = new Collection<ValidationResult>();
bool isValid = Validator.TryValidateObject(this, context, results, true);
if (!isValid)
ValidationResult result = results.SingleOrDefault(p =>
p.MemberNames.Any(memberName =>
memberName == propertyName));
return result == null ? null : result.ErrorMessage;
return null;
#endregion
我可以将它添加到数据库中,但是一旦我尝试更新它,我就会得到一个异常。
我正在使用:
public void UpdatePlace(Place place)
var entity = context.Places.Find(place.Id);
if (entity == null)
throw new InvalidOperationException("Place not found.");
context.Entry(place).CurrentValues.SetValues(place);
context.SaveChanges();
当我到达时
context.Entry(place).CurrentValues.SetValues(place);
我得到一个例外:
System.InvalidOperationException
“不能为类型的实体调用成员'CurrentValues' 'Place' 因为实体在上下文中不存在。 要将实体添加到上下文中,请调用的 Add 或 Attach 方法 数据库集。”
context.Entry
告诉我该实体确实是分离的
但是DbSet.Find()
方法的文档清楚地表明Find()
应该返回一个附加实体,以防在数据库中找到一个实体:
查找具有给定主键值的实体。如果上下文中存在具有给定主键值的实体,则立即返回它而不向存储区发出请求。否则,将向存储请求具有给定主键值的实体,并且此实体(如果找到)将附加到上下文并返回。如果在上下文或存储中没有找到实体,则返回 null。
所以当我尝试获取CurrentValues
时,由于实体已分离,它会抛出Exception
... 但据我所知,应该有一个附加的实体,或者为null,而不是其他任何东西。 ...
我在网上找不到有关此错误的任何信息,我使用 SQL CE 4.0 作为数据库,有人知道发生了什么吗?
我认为每次从Find
获取实体时,我都可以只Attach
,但我仍然想了解我的软件发生了什么,因为这不应该发生。
【问题讨论】:
【参考方案1】:我认为你应该将这一行改为:
context.Entry(entity).CurrentValues.SetValues(place);
【讨论】:
好吧...现在感觉自己傻了哈哈哈,这段代码是从教程中得到的,本来应该多注意复制+粘贴的,教程完全错了,我会通知作者。非常感谢 ErikEJ! youtube.com/watch?v=7SwgqLJCLI8 代码显示在视频的 6:30。 实际上是 4:00 分钟。 补充一点,他确实进行了单元测试,所以显然这段代码是“可信的”....我想这会成为关于测试的一个很好的教训......以上是关于EF DbSet.Find() 返回分离实体的主要内容,如果未能解决你的问题,请参考以下文章
从零开始搭建前后端分离的NetCore(EF Core CodeFirst+Au)+Vue的项目框架之三统一返回数据
EF架构~FluentValidation实体检验与实体分离了
TeamCity 中的 EF6 和 MSTest:实体框架提供程序必须从此类继承,并且“实例”成员必须返回单例实例