自跟踪实体,只附加实体本身而不附加引用

本文关键字:实体 引用 跟踪 | 更新日期: 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模型文件中存在外键属性。

用一种肮脏的解决方法解决了我的问题。我现在插入/更新每个项目,它现在正在工作。希望批量更新,但这似乎不可能。

无论如何,感谢您的努力