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

C# 实体框架在使用AutoMapper后分离虚拟对象,c#,entity-framework,automapper,C#,Entity Framework,Automapper,我已经建立了一个MVC环境,在这里我获取一个实体框架实体,将其映射到一个DTO,供用户修改,然后将DTO映射回EF实体 我的EF课程如下: public class Person { [Key] public int Id { get; set; } public string Name { get; set; } public int AddressId { get; set; } public virtual StreetAddress Address

我已经建立了一个MVC环境,在这里我获取一个实体框架实体,将其映射到一个DTO,供用户修改,然后将DTO映射回EF实体

我的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*/
}
我的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*/
}
从这里,我将这个人映射到一个人,来回映射:

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);
有更好的方法吗?也许有一种方法可以告诉EF,如果某个人的地址ID已经存在于数据库中,则无需插入该地址?

一种方法是亲自和个人插入
地址ID


另一种方法是将实体状态设置为修改:
context.Entry(person.Address).state=EntityState.modified
如图所示

我实际上已经公开了外键,这就是
/*addressId*/
注释的来源,我对问题进行了编辑以使其更清楚。我如何使用公开的外键来帮助我?我还尝试更改person.Address的状态,但失败了,异常是
附加类型为“……StreetAddress”的实体失败,因为相同类型的另一个实体已经具有相同的主键值
这是MVC吗?您的保存逻辑是什么?我个人觉得最简单的方法是在GET中填充我的ViewModel并将其发送到视图,然后在POST中我将对象取回,并在保存之前将更改后的ViewModel字段映射回。是的,这是MVC,至于保存逻辑,我对EF非常陌生,但对于这种特定情况,我只使用
context.Set().Add(person);SaveChanges()
因为精简版的“我的代码”当前只插入新的人员。请尝试将Address navigation属性置零(或在将DTO映射到实体时忽略该属性),但请确保设置了AddressID。
var tracked = context.ChangeTracker.Entries<Address>();
person.Address = tracked.Where(x => x.Entity.Id == person.AddressId).Select(e => e.Entity).FirstOrDefault();