我已经阅读了几篇有关此问题的帖子(例如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; }
}
当我尝试插入如下所示的新任务时,creator
和receiver
相同的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
。
答案 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();
}