如何在EF中移动具有导航属性的子对象

时间:2018-06-06 09:32:43

标签: c# entity-framework

我有两个人可以有Atendee记录。我想合并这两个,保留主要的Atendee,如果他有,否则使用中学的参加者。然后删除辅助。

在SQL中,我会这样写:

UPDATE dbo.atendee SET personid = @main.id WHERE id = @person.atendeeid
DELETE FROM people WHERE id = @person.id

我在EF中尝试了以下操作,但出现错误:

    if (person.AtendeeId != null)
    {
        if (main.AtendeeId == null)
        {
            main.AtendeeId = person.AtendeeId;
            main.Atendeed = person.Atendeed;
        }
        person.AtendeeId = null;
        person.Atendeed = null;
    }

    db.Persons.Remove(person);

错误是:

  

发生了参照完整性约束违规:主键   作为参照完整性约束的一部分的属性不能   除非正在设置,否则在依赖对象未更改时更改   该协会的主要对象。主要对象必须是   已跟踪且未标记为删除

有人可以解释一下搬家时的最佳做法吗?

在C#POCO中。人有

public virtual int? AtendeeId { get; set; }
[ForeignKey("Id")]
public virtual Atendee Atendeed { get; set; }

虽然参加者有:

public virtual int PersonId { get; set; }
public virtual Person Person { get; set; }

在SQL中,Atendees有一个

PersonId(int, not null)

人们有一个

Atendeeid(int, null)

1 个答案:

答案 0 :(得分:3)

使用导航属性来影响移动,而不是FK。在这两种情况下,一定要急切加载孩子。因此,如果一个Person被设置为有一个可选的参与者,其中Person持有AttendeeId,那么您的逻辑就是将一个参与者从一个人移动到另一个人:

targetPerson.Attendee = sourcePerson.Attendee;
sourcePerson.Attendee = null;
context.SaveChanges();

如果目标和来源都是在参与者急切加载的情况下检索的,那么

var targetPerson = context.People.Include(x=>x.Attendee).SingleOrDefault(x=>x.PeopleId == targetId);
var sourcePerson = context.People.Include(x=>x.Attendee).SingleOrDefault(x=>x.PeopleId == sourceId);

通过相关检查确保转移前有与会者。 EF通过导航属性及其代理类和上下文跟踪中的表示最好地完成这些操作,而不是尝试通过ID执行此操作。