asp.net-mvc – 调用SaveChanges()时从更新中排除属性
似乎有两种方法使用“attach”方法更新断开连接的Entity Framework实体.
方法一是简单地将断开连接的实体的状态设置为已修改: myDbContext.Dogs.Attach(dog); myDbContext.Entry(dog).State = EntityState.Modified; myDbContext.SaveChanges(); 这将保存“dog”对象上的所有字段.但是你说你是在一个mvc网页上做的,你只允许编辑Dog.Name,页面上唯一的Dog属性是Name.然后可以做方法二: myDbContext.Dogs.Attach(dog); myDbContext.Entry(dog).Property(o => o.Name).CurrentValue = dog.Name; myDbContext.Entry(dog).Property(o => o.Name).IsModified = true; myDbContext.SaveChanges(); 当有许多属性需要更新时,方法二可能会变得非常冗长.这促使我尝试方法三,在我不想改变的属性上设置IsModified = false.这不起作用,抛出运行时错误“不支持修改属性的设置IsModified为false”: myDbContext.Dogs.Attach(dog); myDbContext.Entry(dog).State = EntityState.Modified; myDbContext.Entry(dog).Property(o => o.Owner).IsModified = false; myDbContext.SaveChanges(); 我更喜欢在任何地方使用Method One,但是在很多情况下我的asp.net mvc视图不包含Dog类的每个标量属性. 我的问题是: >我是否可以在POCO类中使用任何属性来告诉Entity Framework我从不希望该属性更新?例如,[NeverUpdate].我知道[NotMapped]属性,但这不是我需要的. 附:我知道另一种方法,不使用“附加”,只需从数据库中获取一个新对象,更新所需的属性,然后保存.这就是我正在做的事情,但我很好奇是否有一种方法可以使用“附加”,从而避免额外的数据库访问,但这样做的方式不像上面的方法二那么冗长.通过“获取一个新鲜的对象”我的意思是: Dog dbDog = myDbContext.Dogs.FirstOrDefault(d => d.ID = dog.ID); dbDog.Name = dog.Name; myDbContext.SaveChanges(); 解决方法
以下可能有效.
myDbContext.Dogs.Attach(dog); myDbContext.Entry(dog).State = EntityState.Modified; var objectContext = ((IObjectContextAdapter) myDbContext).ObjectContext; foreach (var entry in objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Modified).Where(entity => entity.Entity.GetType() == typeof(Dogs))) { // You need to give Foreign Key Property name // instead of Navigation Property name entry.RejectPropertyChanges("OwnerID"); } myDbContext.SaveChanges(); 如果您想在一行中执行此操作,请使用以下扩展方法: public static void DontUpdateProperty<TEntity>(this DbContext context,string propertyName) { var objectContext = ((IObjectContextAdapter) context).ObjectContext; foreach (var entry in objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Modified).Where(entity => entity.Entity.GetType() == typeof(TEntity))) { entry.RejectPropertyChanges(propertyName); } } 并像这样使用它 // After you modify some POCOs myDbContext.DontUpdateProperty<Dogs>("OwnerID"); myDbContext.SaveChanges(); 如您所见,您可以修改此解决方案以满足您的需求,例如:使用string []属性而不是字符串propertyName作为参数. 建议的方法 更好的解决方案是使用您建议的属性([NeverUpdate]).要使其工作,您需要使用SavingChanges事件(检查我的blog): void ObjectContext_SavingChanges(object sender,System.Data.Objects.SavingChangesEventArgs e) { ObjectContext context = sender as ObjectContext; if(context != null) { foreach(ObjectStateEntry entry in context.ObjectStateManager.GetObjectStateEntries(EntityState.Modified)) { var type = typeof(entry.Entity); var properties = type.GetProperties(); foreach( var property in properties ) { var attributes = property.GetCustomAttributes(typeof(NeverUpdateAttribute),false); if(attributes.Length > 0) entry.RejectPropertyChanges(property.Name); } } } } // Check Microsoft documentation on how to create custom attributes: // http://msdn.microsoft.com/en-us/library/sw480ze8(v=vs.80).aspx public class NeverUpdateAttribute: SystemAttribute { } //In your POCO public class Dogs { [NeverUpdate] public int OwnerID { get; set; } } 警告:我没有编译此代码.我不在家 :/ 警告2:我刚刚阅读了MSDN documentation,它说:
我不确定在附加修改后的实体时它的行为是什么.我明天会试试. 警告3:我现在已经尝试过了.此解决方案有效.使用RejectPropertyChanges()方法拒绝的属性不会在持久性单元(数据库)中更新. 但是,如果通过调用Attach()附加更新的实体,则在SaveChanges()之后当前上下文仍然是脏的.假设数据库中存在以下行: Dogs ID: 1 Name: Max OwnerID: 1 请考虑以下代码: var myDog = new Dogs(); myDog.ID = 1; myDog.Name = Achilles; myDog.OwnerID = 2; myDbContext.Dogs.Attach(myDog); myDbContext.Entry(myDog).State = EntityState.Modified; myDbContext.SaveChanges(); SaveChanges()之后的数据库的当前状态: Dogs: ID: 1 Name: Achilles OwnerID: 1 SaveChanges()之后的myDbContext的当前状态: var ownerId = myDog.OwnerID; // it is 2 var status = myDbContext.Entry(myDog).State; // it is Unchanged 那么你应该怎么做?在SaveChanges()之后分离它: Dogs myDog = new Dogs(); //Set properties ... myDbContext.Dogs.Attach(myDog); myDbContext.Entry(myDog).State = EntityState.Modified; myDbContext.SaveChanges(); myDbContext.Entry(myDog).State = EntityState.Detached; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net – K运行时使用的.Net完整框架和.Net Core Framewo
- ASP.NET MVC中的基本认证5
- ASP.NET MVC验证属性和Jquery
- asp.net-mvc – 使用web.config关闭MVC中的身份验证
- asp.net-web-api – 使用OAuth和单页应用程序实现Web API
- asp.net-mvc – MvcSiteMap:未到达动态节点提供程序
- 如何在ASP.net中取消事件冒泡?
- asp.net-mvc-3 – 自定义RazorViewEngine会出现页面错误
- VS2005(c#)项目调试问题解决方案集锦 转
- asp.net – 在IIS 7或IIS 7.5集成模式下,默认文档中可能不会
- asp.net – 基类包含字段“ScriptManager1”,但其
- asp.net – 在Google Chrome浏览器中加载两次
- asp.net-mvc – Web API 2需要使用尾部斜杠来使自
- ASP.NET MVC下的四种验证编程方式[续篇]
- asp.net – 从Classic ASP调用需要.NET类型的.NE
- asp.net – linq中的switch语句
- Dapper和MVC VNext中的问题
- asp.net – 将web.web应用程序池添加到web.confi
- asp.net中利用Jquery+Ajax+Json实现无刷新分页的
- asp.net – 如何从WCF客户端拦截raw soap reques