获取“此 EntitySet 中已存在具有相同身份的实体”但EntitySet是空的

发布于 2024-09-01 00:11:00 字数 2649 浏览 3 评论 0原文

当我尝试向 EntitySet 添加新项目时,出现以下异常:

具有相同身份的实体 此实体集中已存在

但是,当我检查 EntitySet 时,其计数为 0。

有什么想法为什么当集合为空时我会收到此错误?如果集合中没有任何项目,那么实体怎么可能已经存在于集合中呢?

更新

我已经缩小了范围。仅当我将项目添加到集合中,将其删除,然后重新添加时,才会发生这种情况。即使该项目不再位于 EntitySet 中,它仍然以某种方式记住它。我需要做什么才能让它忘记?

更新:以下是所涉及的类和逻辑的一些代码片段。

服务器实体:

public class PhotoDto
{
    [Key]
    [Editable(false)]
    public int Id { get; set; }

    /* clip */

    [Include]
    [Association("Photo_Destination", "Id", "PhotoId")]
    public EntitySet<PhotoDestinationDto> Destinations { get; set; }
}

public class PhotoDestinationDto : BaseDestionationDto
{
    [Key]
    [Editable(false, AllowInitialValue = true)]
    public int PhotoId { get; set; }

    [Key]
    [Editable(false, AllowInitialValue = true)]
    public bool IsAnnotated { get; set; }

    [Key]
    [Editable(false, AllowInitialValue = true)]
    public int DropZoneId { get; set; }
}

public class BaseDestinationDto
{
    [Key]
    [Editable(false, AllowInitialValue = true)]
    public Guid DatabaseUid { get; set; }

    [Key]
    [Editable(false, AllowInitialValue = true)]
    public string Unit { get; set; }

    [Key]
    [Editable(false, AllowInitialValue = true)]
    public string EqCircId { get; set; }

    [Key]
    [Editable(false, AllowInitialValue = true)]
    public string EqType { get; set; }
}

PhotoDestinationDto 的客户端 GetIdentity():

/// <summary>
/// Computes a value from the key fields that uniquely identifies this entity instance.
/// </summary>
/// <returns>An object instance that uniquely identifies this entity instance.</returns>
public override object GetIdentity()
{
    if ((((this._eqCircId == null) 
                || (this._eqType == null)) 
                || (this._unit == null)))
    {
        return null;
    }
    return EntityKey.Create(this._dropZoneId, this._eqCircId, this._eqType, this._isAnnotated, this._photoId, this._unit, this._databaseUid);
}

要删除照片目标客户端:

PhotoDto photo = GetPhotoDto();
PhotoDestinationDto destToRemove = photo.Destinations.First(x => x.DropZoneId == 1);
photo.Destinations.Remove(destToRemove);

要添加照片目标客户端:

var dest = new PhotoDestinationDto
{
    DropZoneId = zoneId,
    EqCircId = selectedEqCircId,
    EqType = selectedEqType,
    Unit = selectedUnit,
    PhotoId = id,
    DatabaseUid = selectedDatabaseId
};

p.Destinations.Add(dest); // this is where exception is thrown. p.Destinations.Count is 0 here.

When I try to add a new item to my EntitySet, I'm getting this exception:

An entity with the same identity
already exists in this EntitySet

However, when I inspect the EntitySet its count is 0.

Any ideas why I would be getting this error when the set is empty? How could an entity already exist in the set if the set has no items in it?

UPDATE

I've narrowed this down a bit more. This is only happening if I add the item to the set, remove it, then re-add it. Even tho the item isn't in the EntitySet any more it is still remembering it somehow. What do I need to do to make it forget?

UPDATE: Here are some code snippets for the classes and logic involved.

Server Entities:

public class PhotoDto
{
    [Key]
    [Editable(false)]
    public int Id { get; set; }

    /* clip */

    [Include]
    [Association("Photo_Destination", "Id", "PhotoId")]
    public EntitySet<PhotoDestinationDto> Destinations { get; set; }
}

public class PhotoDestinationDto : BaseDestionationDto
{
    [Key]
    [Editable(false, AllowInitialValue = true)]
    public int PhotoId { get; set; }

    [Key]
    [Editable(false, AllowInitialValue = true)]
    public bool IsAnnotated { get; set; }

    [Key]
    [Editable(false, AllowInitialValue = true)]
    public int DropZoneId { get; set; }
}

public class BaseDestinationDto
{
    [Key]
    [Editable(false, AllowInitialValue = true)]
    public Guid DatabaseUid { get; set; }

    [Key]
    [Editable(false, AllowInitialValue = true)]
    public string Unit { get; set; }

    [Key]
    [Editable(false, AllowInitialValue = true)]
    public string EqCircId { get; set; }

    [Key]
    [Editable(false, AllowInitialValue = true)]
    public string EqType { get; set; }
}

Client side GetIdentity() for PhotoDestinationDto:

/// <summary>
/// Computes a value from the key fields that uniquely identifies this entity instance.
/// </summary>
/// <returns>An object instance that uniquely identifies this entity instance.</returns>
public override object GetIdentity()
{
    if ((((this._eqCircId == null) 
                || (this._eqType == null)) 
                || (this._unit == null)))
    {
        return null;
    }
    return EntityKey.Create(this._dropZoneId, this._eqCircId, this._eqType, this._isAnnotated, this._photoId, this._unit, this._databaseUid);
}

To remove photo destination client side:

PhotoDto photo = GetPhotoDto();
PhotoDestinationDto destToRemove = photo.Destinations.First(x => x.DropZoneId == 1);
photo.Destinations.Remove(destToRemove);

To add photo destination client side:

var dest = new PhotoDestinationDto
{
    DropZoneId = zoneId,
    EqCircId = selectedEqCircId,
    EqType = selectedEqType,
    Unit = selectedUnit,
    PhotoId = id,
    DatabaseUid = selectedDatabaseId
};

p.Destinations.Add(dest); // this is where exception is thrown. p.Destinations.Count is 0 here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

怪我入戏太深 2024-09-08 00:11:00

从您的代码 Unit = selectedUnitp.Destinations.Add(dest); 以及您描述的其他症状来看,您似乎有完全相同的情况。我的以下发现已经解决了我的问题。

如果您因此而在数据库中出现任何重复的实体,也很感兴趣。我得到了之前已经保存的行,神奇地转向New,然后变成了重复记录。下面这个简单的更改再次修复了它。


我发现存在一个竞争条件,如果您创建一个实体并在将父实体添加到其实体集之前立即为其分配外键关系,则可能会出现此错误。

事实证明,设置外键关系的行为实际上会将实体添加到其相应的实体集 - 但有时会导致竞争条件,特别是当您的 UI 正在加载、保存和清除实体集时。

坏:

var todo = new TODO();
todo.Status = TODOContext.Statuses.Single(x=>x.Status == "Unknown");
todo.AssignedTo = TODOContext.Users.Single(x=>x.UserName == "JSMITH");
TODOContext.TODOs.Add(todo); // adding entity after setting FK

好:

var todo = new TODO();
TODOContext.TODOs.Add(todo); // add entity before setting FK
todo.Status = TODOContext.Statuses.Single(x=>x.Status == "Unknown");
todo.AssignedTo = TODOContext.Users.Single(x=>x.UserName == "JSMITH");

Juding by your code Unit = selectedUnit and p.Destinations.Add(dest); and the other symptoms you describe you seem to have the exact same situation. My findings below have fixed the problem for me.

Interested also if you ended up with any duplicated entities in your database as a result of this. i was getting rows already previously saved magically turning to New and then becoming dupe records. Again this simple change below fixed it.


There is a race condition i discovered that can give this error if you create an entity and immediately assign foreign key relationships to it before adding the parent entity to its entity set.

Turns out the very act of setting the foreign key relationship actually adds the entity to its corresponding entity set - but sometimes causes a race condition, especially if your UI is loading and saving and clearing entity sets.

bad:

var todo = new TODO();
todo.Status = TODOContext.Statuses.Single(x=>x.Status == "Unknown");
todo.AssignedTo = TODOContext.Users.Single(x=>x.UserName == "JSMITH");
TODOContext.TODOs.Add(todo); // adding entity after setting FK

good:

var todo = new TODO();
TODOContext.TODOs.Add(todo); // add entity before setting FK
todo.Status = TODOContext.Statuses.Single(x=>x.Status == "Unknown");
todo.AssignedTo = TODOContext.Users.Single(x=>x.UserName == "JSMITH");
虐人心 2024-09-08 00:11:00

好的,看到您的代码后我发现了问题。从 EntityCollection 中删除时,实体实际上并未被删除(如在待删除中) - 仅切断关联,并将 FK 设置为其默认值。因此,您的 photo.Destinations.Remove() 调用实际上并未从 DomainContext (ctxt.PhotoDestinationDtos EntitySet) 中删除实体。这就是您遇到缓存冲突的原因。

要实际删除它,您应该调用 ctxt.PhotoDestinationDtos.Remove。

Ok, after seeing your code I see the issue. When removing from an EntityCollection the entity isn't actually removed (as in a pending delete) - the association is only severed, with FKs set to their default values. So your photo.Destinations.Remove() call doesn't actually remove the entity from the DomainContext (ctxt.PhotoDestinationDtos EntitySet). That's why you're getting the cache collision.

To actually remove it, you should be calling ctxt.PhotoDestinationDtos.Remove.

尬尬 2024-09-08 00:11:00

我遇到了同样的问题,后来我意识到数据库中有一行 ID 列为“0”,每次我们尝试保存新记录时,它最初都会在 ID 列中插入 0,我删除了已经存在并且我的代码工作得很好,
我没有更改DomainService类创建的Inser方法,

I had the same issue, I later realised that there is a row in the database where the ID column was "0", everytime we try to save the new record it initially inserts it with 0 in the ID column, I deleted the one that is already present and my code was working perfectly fine,
I did not change the Inser method created by the DomainService class,

梦与时光遇 2024-09-08 00:11:00

任何仍然收到此错误的人,在尝试上述修复后我仍然收到错误。最后,我可以通过为我的身份 ID 分配一个新的唯一 ID 来修复它,即使这不会在数据库中更新。

Anyone who is still getting this error, after trying above fixes I was still getting the error. Finally I am able to fix it by assigning a new Unique id to my Identity id even though this won't be updated in the database.

懒的傷心 2024-09-08 00:11:00

您是否确保在该表的数据库中正确定义了 PK/身份,并且它反映在您的模型中?尝试重写 DomainService 中的 OnError 以获取有关服务器端异常的更多信息。 (您在客户端/Silverlight 端收到此错误,对吧?)

Have you made sure you have a PK/identity properly defined in your db on that table, and it is reflected in your model? Try overriding OnError in your DomainService to get more info on the server-side exception. (You're getting this error on the client/Silverlight side, right?)

俏︾媚 2024-09-08 00:11:00

当您从 EntitySet 中删除实体时,应在 SubmitChanges() 期间删除数据库中的关联记录。因此,该实体必须继续跟踪该实体 - 即使在该实体已被删除之后。它是生成删除语句所必需的。

尽管它不再直接在 EntitySet 中可用(下图中的“结果视图”节点),但该实体在私有 _IdentityCache 属性中进行跟踪。在下面的示例中,我在 EntitySet 中只有一个实体...

在此处输入图像描述

...但是是 _identityCache 属性中的两项。

在此处输入图像描述

您可以使用以下代码访问 EntitySet 跟踪的 EntityState 为已删除的实体。

entitySet.EntityContainer.GetChanges().RemovedEntities

在您的情况下,您应该重用上面的RemovedEntities集合中的现有实体,或者在添加具有相同键的新实体之前将其分离。

When you remove an entity from an EntitySet, the associated record in the database should be deleted during SubmitChanges(). For this reason, the entity must continue to track the entity - even after it has been removed. It is required for the generation of the delete statement.

Although it is no longer available within the EntitySet directly (the Results View node in the image below), the entity is tracked within the private _IdentityCache property. In the example below, I have only a single entity within the EntitySet...

enter image description here

...however there are two items in the _identityCache property.

enter image description here

You can access the entities tracked by an EntitySet that have an EntityState of Deleted using the following code.

entitySet.EntityContainer.GetChanges().RemovedEntities

In your case, you should either reuse the existing entity in the RemovedEntities collection from above or detach it before adding a new one with the same key.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文