Selftracking Entities,仅附加实体本身而不引用

时间:2012-03-20 13:02:35

标签: c# linq entity-framework entity-framework-4 self-tracking-entities

使用:SQL Server 2008 R2,Entityframework 4.3.1

我的场景:我在服务端从数据库中读取了我的对象。我正在使用T4模板“Selftracking实体”从objectcontext创建对象。这些对象被传递到客户端,在那里它们被操纵并发送回服务。

通过selftracking我可以看到客户端上已经更改了哪些属性。

我更新实体的方法如下:

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”。可以有多个研讨会参考相同的Dozentobject。因此,当我使用相同的引用附加两个研讨会时,我得到以下例外:

  

ObjectStateManager中已存在具有相同键的对象。   ObjectStateManager无法使用相同的键跟踪多个对象

我有什么想法可以解决这个问题?是否有可能只附加普通对象而没有引用但包含ForeignKey ID?我可以尝试其他任何方法吗?

2 个答案:

答案 0 :(得分:0)

您的代码存在一些问题。首先,如果您使用自我跟踪实体,则无需更改服务中的更改跟踪器状态。由于自我跟踪实体具有自己的状态,因此如果您尝试持久保存任何实体,则上下文将根据实体的跟踪状态执行相关操作。 因此,仅附加更新的实体并调用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。因此,当您为每个更新的Seminar实体调用attach时,会将新的Dozent实体附加到对象上下文(实际上是具有相同id的不同对象);这会导致主键违规。

为了解决这个问题,不是发送研讨会列表,而是发送与研讨会实体有一对多关系的实体(当然,如果你有这样的实体)。

或者,如果您没有父实体,请尝试设置研讨会实体的外键值,而不设置相关的Dozent导航属性。您应该首先确保EDMX模型文件中存在外键属性。

答案 1 :(得分:0)

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

非常感谢你的efford