简体   繁体   English

实体框架在使用 AutoMapper 后分离虚拟对象

[英]Entity Framework detached virtual object after using AutoMapper

I have set up an MVC environment where I am taking an Entity Framework entity, mapping it to a DTO for the user to modify and then mapping the DTO back to the EF entity.我已经建立了一个 MVC 环境,我在其中使用实体框架实体,将其映射到 DTO 以供用户修改,然后将 DTO 映射回 EF 实体。

My EF classes are as follows:我的EF课程如下:

public class Person
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    public int AddressId { get; set; }
    public virtual StreetAddress Address { get; set; }
    /*More stuff here*/
}
//For the purpose of this example lets assume that addresses cannot be changed, they are read-only
public class StreetAddress
{
    [Key]
    public int Id { get; set; }
    public string StreetName { get; set; }
    /*More stuff here*/
}

My DTO is:我的 DTO 是:

public class PersonDTO
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int AddressId { get; set; }
    public StreetAddress Address { get; set; }
    /*More stuff here*/
}

From here I map the Person to a PersonDTO and back again:从这里我将 Person 映射到 PersonDTO 并再次返回:

Person person = /*retrieve from database*/;
PersonDTO dto = Mapper.Map<PersonDTO>(person);

// send dto to user, user updates name, user sends dto back
// the address object is the same, but it might have been converted to JSON or something like that during transport

Person person = Mapper.Map<Person>(dto);

So I now have a Person ready to save to the database.所以我现在有一个 Person 准备好保存到数据库中。 The StreetAddress object still has the same information, however now EF sees the Address as detached. StreetAddress 对象仍然具有相同的信息,但是现在 EF 将 Address 视为分离的。 I can't use context.Attach(Address) because the context already has a StreetAddress with the same Key attached, and attempting to do so causes an exception to be thrown.我不能使用context.Attach(Address)因为上下文已经有一个带有相同 Key 的 StreetAddress,并且尝试这样做会导致抛出异常。

If I choose to ignore the detached Address and add this new person to my database, EF sees the Address as a brand new object and inserts it into the database, causing the address row in the database to be duplicated, same details, new ID.如果我选择忽略分离的地址并将这个新人添加到我的数据库中,EF 会将地址视为一个全新的对象并将其插入数据库,从而导致数据库中的地址行重复,详细信息相同,新 ID。

My current solution is to replace the Address object with the one that is already attached to the context:我当前的解决方案是将 Address 对象替换为已经附加到上下文的对象:

var tracked = context.ChangeTracker.Entries<Address>();
person.Address = tracked.Where(x => x.Entity.Id == person.AddressId).Select(e => e.Entity).FirstOrDefault();

Is there a better way to do this?有一个更好的方法吗? perhaps a way to tell EF that if there is a Person with an Address where the Address ID is already in the database there is no need to insert it?也许是一种告诉 EF 如果有一个地址的人的方法,其中地址 ID 已经在数据库中,则不需要插入它?

One way is to expose your FK AddressId in Person and PersonDTO.一种方法是使您的FK AddressId在人与PersonDTO。

Another is to set the entity state to modified: context.Entry(person.Address).State = EntityState.Modified;另一种是将实体状态设置为已修改: context.Entry(person.Address).State = EntityState.Modified; as shown here如图所示这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM