自跟踪实体,只附加实体本身而不附加引用
本文关键字:实体 引用 跟踪 | 更新日期: 2023-09-27 18:28:35
使用:SQL Server 2008 R2,Entityframework 4.3.1
我的场景:我从服务端的数据库中读取对象。我使用T4模板"Selftracking entities"从对象上下文创建对象。这些对象被传递到客户端,在那里它们被操作并发送回服务。
通过自我跟踪,我可以看到客户端的属性发生了变化。
我更新实体的方法如下:
using ( var transaction = new TransactionScope() )
{
var connection = this.ConnectionManager.GetConnectionstring( AcademyOne.Models.Connection.A1Databases.A1VerwaltungEntity );
using ( var context = new istis.AcademyOne.Models.Models.A1Verwaltung.VerwaltungModelsContext( connection.Connectionstring ) )
{
foreach ( var seminar in seminare )
{
context.Seminar.Attach( seminar );
context.ObjectStateManager.ChangeObjectState( seminar, StateValueConverter.GetEquivalentEntityState( seminar.ChangeTracker.State ) );
}
context.SaveChanges( SaveOptions.DetectChangesBeforeSave );
}
transaction.Complete();
}
我的问题。实体"研讨会"是指"Dozent"。可以有多个研讨会引用同一个Dozentoject。因此,当我将两个研讨会都附上相同的参考资料时,我会得到以下例外:
ObjectStateManager中已存在具有相同键的对象。ObjectStateManager无法跟踪具有相同密钥的多个对象
有什么想法我能解决这个问题吗?是否有可能只附加没有引用但包含ForeignKey ID的普通对象?我还可以尝试其他方法吗?
您的代码有一些问题。首先,如果您使用的是自跟踪实体,则不需要更改服务中的changetracker状态。由于自跟踪实体携带自己的状态,如果您试图持久化任何实体,上下文将根据实体的跟踪状态执行相关操作。因此,仅附加更新后的实体并调用savechanges就足以保存实体。
using ( var transaction = new TransactionScope() )
{
var connection = this.ConnectionManager.GetConnectionstring( AcademyOne.Models.Connection.A1Databases.A1VerwaltungEntity );
using ( var context = new istis.AcademyOne.Models.Models.A1Verwaltung.VerwaltungModelsContext( connection.Connectionstring ) )
{
foreach ( var seminar in seminare )
{
//The following line shall be commented out
//context.Seminar.Attach( seminar );
context.Seminar.ApplyChanges( seminar );
//The following line shall be commented out.
//context.ObjectStateManager.ChangeObjectState( seminar, StateValueConverter.GetEquivalentEntityState( seminar.ChangeTracker.State ) );
}
context.SaveChanges( SaveOptions.DetectChangesBeforeSave );
}
transaction.Complete();
}
其次,我认为这个问题的出现是因为Dozent实体的状态是Created。因此,当您为每个更新的研讨会实体调用attach时,一个新的Dozent实体被附加到对象上下文(实际上是具有相同id的不同对象);这导致主键违反。
为了解决这个问题,不要发送研讨会列表,而是发送一个与研讨会实体有一对多关系的实体(当然,如果你有这样的实体)。
或者,如果没有父实体,请尝试设置研讨会实体的外键值,而不设置相关的Dozent导航属性。您应该首先确保EDMX模型文件中存在外键属性。
用一种肮脏的解决方法解决了我的问题。我现在插入/更新每个项目,它现在正在工作。希望批量更新,但这似乎不可能。
无论如何,感谢您的努力