实体框架链表

5
我有一个实体(我正在使用Code First),它看起来像这样:
public class Node
{
    public int ID { get; set; }
    public string SomeInfo { get; set; }

    public virtual Node Previous { get; set; }
    public virtual Node Next { get; set; }
}

例如,保存下一个节点是没有问题的。但是,如果前一个节点的ID为1,并且我试图将其下一个节点(即ID=1的节点)设置为2,则会抛出此异常信息:
“无法将对象添加到对象上下文中。该对象的EntityKey具有一个ObjectStateEntry,该条目指示该对象已经参与了不同的关系。”
我是这样保存节点的:
int nextId;
int previousId;
if (int.TryParse(Request["previous"], out previousId))
   node.Previous = this.nodeRepository.GetSingle(previousId);

if (int.TryParse(Request["next"], out nextId))
   node.Next = this.nodeRepository.GetSingle(nextId);

this.nodeRepository.Update(node);

更新内容如下:
public virtual void Update(T entity)
{
    this.context.Entry(GetSingle(entity.ID)).State = EntityState.Detached;
    this.context.Entry(entity).State = EntityState.Added;
    this.context.Entry(entity).State = EntityState.Modified;

    this.Save();
}

"并且像这样使用 GetSingle:"
public virtual T GetSingle(object id)
{
    var query = this.entities.Find(id);
    return query;
}

更新1:
异常所在的代码行位于Update方法中:
this.context.Entry(entity).State = EntityState.Modified;

1
我认为问题在于单向关系。在这种情况下,EF仅支持共享主键关联,这基本上意味着如果 Node.ID = 1,那么 Node.Previous.IDNode.Next.ID 也必须是 1。没有其他的值可用。可以说,您只能从一个节点创建一个循环到自身。在哪一行您得到了异常?当您得到异常时,node.IDpreviousIdnextId 具有哪些值? - Slauma
实际上,这似乎不是问题所在。情况是这样的:node.id = 2; node.previous.id = 1。现在我去到node.id = 1并尝试设置node.next.id = 2 - 只有在那时才会抛出异常。 - Unknown
你是否使用Fluent API(或数据注释)进行映射?对我来说,模型无法创建,我得到了“无法确定关联的主要端点”异常。你使用的EF版本是哪个? - Slauma
我认为问题出在你的 EF 设置上。如果设置正确,那么设置 node[id=2].previous.id = 1 并保存更改应该会导致 node[id=1].next.id = 2,因为 EF 只设置关系的一端就可以设置另一端。如果你的设置是正确的。请分享流畅的 API。 - Mariusz.W
请展示FLUENT API映射。问题可能在于FK关系定义的方式。简短的回答是,即使逻辑上它们可能是单个关系,你也应该将FK声明为MANY到MANY关系。 - phil soady
1个回答

0

你的上下文是否在 Using 块中,并在某个时刻被处理掉了?我曾经遇到过类似的“无法将对象添加到对象上下文中”的错误。我建议在你的模型中添加 Previous 和 Next 的 Id,并使用它们来更新外键。

public class Node
{
    public int ID { get; set; }
    public string SomeInfo { get; set; }

    public virtual Node Previous { get; set; }
    public int PreviousId { get; set; }
    public virtual Node Next { get; set; }
    public int NextId { get; set; }
}

更新外键...

int nodeId;  // I'm assuming you know the id of node you want updated.

int nextId;
int previousId;


using (var context = new Context()) 
{     
    // Perform data access using the context 
    var node = context.Nodes.find(nodeId);
    node.NextId = nextId;
    node.PreviousId = previousId;
    context.SaveChanges();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接