附加更新entity framework

我正在尝试使用附加使用EF 5.x对表进行更新。 此表具有所需的其他字段,但它是现有行。 所以我试图更新,没有任何提取。 userid是表的主键。 我正在尝试更新状态。 但它会抛出一个EntityValidationErrors,表示需要密码,这是另一个必填字段,但不是主键。 由于这是对现有行的更新,为什么需要提供需要更新的字段?

var webUser = new WebUser() { UserId = webUserId, OnlineStatus = (sbyte)status }; using (var dbxupdate = new xEntities()) { try { dbxupdate.WebUsers.Attach(webUser); dbxupdate.Entry(webUser).State = EntityState.Modified; dbxupdate.Entry(webUser).Property(x => x.OnlineStatus).IsModified = true; dbxupdate.SaveChanges(); } catch (DbEntityValidationException dbEx) { foreach (var validationErrors in dbEx.EntityValidationErrors) { foreach (var validationError in validationErrors.ValidationErrors) { Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage); } } } } 

在entity framework中,如果没有为其他字段设置适当的值,则无法更新字段。 所以最好为你的工作使用存储过程。 另一种方法是获取记录然后更新字段。

.Attach()实际上只对更新分离场景中的实体很有用,如下所示:

 User entity = null; using (var db = new DbContext()) { entity = (from p in db.Users where p.id == 1 select p).FirstOrDefault(); System.Diagnostics.Trace.WriteLine(entity.Name); //Outputs "Jane Doe" } entity.Name = "John Doe" //Modified while no longer connected to database using (var db = new DbContext()) { db.Users.Attach(entity); db.Entry(entity).Property(a => a.Name).IsModified = true; db.SaveChanges(); System.Diagnostics.Trace.WriteLine(entity.Name); //Now outputs "John Doe" } 

在您的方案中,您正在创建的实体未被其密钥检索,并且数据库将其视为一个全新的实体。 我假设您的密码是一个不可为空的字段,然后在尝试保存更改时导致EF抛出错误。 如果您没有任何此类错误,那么EF将自动清空您未修改的任何字段,然后保存实体(这不是您正在寻找的结果)。

为了进行您真正想要的更改,请尝试以下操作:

 using (var db = new DbContext()) { db.Users.Single(a => a.id == 1).OnlineStatus = (sbyte)status; db.SaveChanges } 

然后添加您想要的任何其他error handling/validation代码。 或者,您可以将实体存储在变量中,以便一次更改多个字段。 EF应自动确定哪些值已更改,并仅生成进行这些更改所需的SQL。 意思是如果你有类似的东西:

 foreach (var item in entityList) { var entity = db.Users.Single(a => a.id == item.id); entity.Name = item.Name; entity.Address = item.Address; } 

那么EF应该只更新实际受此代码影响的实体/字段。 如果名称或地址保持不变,则EF将在将更改保存到数据库时跳过该实体的该字段。

无论是从数据库附加还是加载,实体都会在保存时进行validation。 如果使用validation属性或validation方法,则实体必须通过validation才能保存。

如果您在密码字段中有[Required]属性,我认为您很困难。 您可能必须加载实体,然后更新信息而不是仅附加它。

试试这个:替换第一行(将其放在using语句中)
var wu = dbxupdate.webUsers.single(i=>i.id== webUserId);
wu.OnlineStatus = whatever;

代码继续…为了更新实体,您必须获得它的实例。 否则你要创建一个新的属性,其中未声明的属性获取null值。