public partial class User { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int ID { get; set; } [StringLength(30)] [Required] public string LoginName { get; set; } [StringLength(120)] [Required] [DataType(DataType.Password)] public string Pwd { get; set; } [StringLength(50)] public string Phone { get; set; } [StringLength(100)] public string WebSite { get; set; } ... ... }
如上面的示例代码所示, LoginName 和 Pwd 是 Required 的。
某些时候我只想更某些字段,比如在某个操作中,我只想更新 WebSite:
public void UpdateUser(User user , params string[] properties) { this.rep.DB.Users.Attach(user); this.rep.DB.Configuration.ValidateOnSaveEnabled = false; var entry = this.rep.DB.Entry(user); foreach(var prop in properties) { var entProp = entry.Property(prop); //var vas = entProp.GetValidationErrors(); entProp.IsModified = true; } this.rep.DB.SaveChanges(); this.rep.DB.Configuration.ValidateOnSaveEnabled = true; }
var user = new User(){ ID = 1, WebSite = "http://www.stackoverflow.com" } UpdateUser(user, "WebSite")
这样做,可以很好的运行,但是ValidateOnSaveEnabled 是 false, 如果将这个值设为 true ,就会因为 LoginName 和 Pwd 是 Required 的,而引起验证不通过。
有没有办法,在 ValidateOnSaveEnabled 为 true 的情况下,不去验证 LoginName 和 Pwd, 只验证 WebSite ?
谢谢
可以啊,方法有很多。千言万语不如一段代码,给段代码:
public class PartialValidationManager { private IDictionary<object, string[]> dictionary = new Dictionary<object, string[]>(); //添加需要部分验证的实体对象 public void Add(object entity, string[] propertyNames) { dictionary.Add(entity, propertyNames); } //移除需要部分验证的实体对象 public void Remove(object entity) { dictionary.Remove(entity); } //对象是要我验证的吗? public bool IsResponsibleFor(object entity) { return dictionary.ContainsKey(entity); } //验证 public void ValidateEntity(DbEntityValidationResult result) { var entry = result.Entry; foreach (var propertyName in dictionary[entry.Entity]) { foreach (var error in entry.Property(propertyName).GetValidationErrors()) { result.ValidationErrors.Add(error); } } } } public class ....Context : DbContext { //... public PartialValidationManager PVManager { get; private set; } //... public BlogContext() { this.PVManager = new PartialValidationManager(); } //... protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entry, IDictionary<object, object> items) { if (PVManager.IsResponsibleFor(entry.Entity)) { var result = new DbEntityValidationResult(entry, new List<DbValidationError>()); PVManager.ValidateEntity(result); return result; } else { return base.ValidateEntity(entry, items); } } }
然后, 调用的时候:
//.... public void UpdateUser(User user , params string[] properties) { var entry = this.rep.DB.Entry(user); this.rep.DB.PVManager.Add(user, properties); foreach(var prop in properties) { entry.Property(prop).IsModified = true; } this.rep.DB.SaveChanges(); this.rep.DB.PVManager.Remove(user); } //...好像有点不够robust, 自己改进吧
我目前是这样解决的,更新一个实体时,先attach这个实体(选择出来后进行attach操作),然后进行修改,最后用commit把更新提交到数据库
用这种方式不存在你遇到的问题,因为attach后该有的值都有了
就是为了避免先取一次,我才这样做。
@xling: 哦,那我也关注下这个问题,看有没有更好的解决方案