具有相同类型和ID的多个导航属性的实体框架插入对象

时间:2018-10-04 13:35:21

标签: c# entity-framework entity-framework-6

我已经阅读了几篇有关此问题的帖子(例如Why can't EF handle two properties with same foreign key, but separate references/instances?),但没有一个提供令人满意的解决方案。

使用EF6,插入具有两个导航属性的对象会失败,当这些属性具有相同的类型,表示相同的条目(即具有相同的主键值)但属于两个不同的对象实例时。

设置:

public abstract class EntityBase
{
    public int Id { get; set; }
    public bool IsTransient => Id <= 0;
}

public class Person : EntityBase
{
    public string Name { get; set; }
}

public class Task : EntityBase
{
    public int CreatorId { get; set; }
    public int ReceiverId { get; set; }
    public string Text { get; set; }

    public Person Creator { get; set; }
    public Person Receiver { get; set; }
}

当我尝试插入如下所示的新任务时,creatorreceiver相同的Person(即具有相同的{{1} } value)。例外是:“ ...因为多个'Person'类型的实体具有相同的主键值。”

Id

可以使用以下代码避免出现异常:

public void AddTask(string text, Person creator, Person receiver)
{
    using (var context = new MyEntities())
    {
        Task task = new Task()
        {
            Text = text,
            Creator = creator,
            Receiver = receiver
        };
        context.Task.Add(task);
        context.Entry(creator).State = EntityState.Unchanged;
        context.Entry(receiver).State = EntityState.Unchanged; // Exception is raised here

        context.SaveChanges();
    }
}

问题:除了在插入之前检查导航属性的ID值之外,还有两种简便的方法可以避免异常吗?

这是一个简单的示例。在此处显示的手动检查非常麻烦的情况下,要插入很多复杂的对象图。

编辑:异常消息为(德语):

  

System.InvalidOperationException:Fehler beim Speichern oder   典型的工业大学   'Person'gleichenPrimärschlüsselwertaufweisen。   Stellen Sie sicher,表演《 Festgelegte》杂志原著   eindeutig sind。原始日期银行   Datenbank和实体框架中的Müssen   孔菲格里尔特·塞纳河。 Verwenden Sie den实体设计师数据库   第一/模型第一知识。 Verwenden Sie die Fluent-API   'HasDatabaseGeneratedOption'或'DatabaseGeneratedAttribute'   代码优先配置。

之所以明确设置public void AddTask(string text, Person creator, Person receiver) { using (var context = new MyEntities()) { Task task = new Task() { Text = text, Creator = creator, Receiver = receiver }; context.Task.Add(task); context.Entry(creator).State = EntityState.Unchanged; if (creator.Id == receiver.Id) task.Receiver = creator; else context.Entry(receiver).State = EntityState.Unchanged; context.SaveChanges(); } } 是因为我正在处理分离的对象。如果我不设置EntityState对象的状态,它将作为新条目插入。为避免这种情况,我将其标记为Person

1 个答案:

答案 0 :(得分:0)

您可以设置ID:

using (var context = new MyEntities())
{
    Task task = new Task()
    {
        Text = text,
        CreatorId = creator.Id,
        ReceiverId = receiver.Id
    };
    context.Task.Add(task);
    context.SaveChanges();
}