如何使用实体框架分离的对象



你好社区我一直在努力解决这个问题很长一段时间了,我使用的是blazor webassembly、dotnet core和EntityFramework,我想更新我的person对象的数据,这个对象包含相关的数据,邻域、市镇和州,如果我只更新person对象,如果它更新了,它会很好,但是,如果在查询中,我使用inlcude包含导航属性,它将不再更新导航属性

错误:

System.InvalidOperationException:实体类型"Status"的实例无法跟踪,因为具有相同键值的另一个实例{"状态ID"}已被跟踪。附着现有时实体,确保只有一个实体实例具有给定的键值已附加。

我看到已经有类似的问题了,但事实是我找不到解决问题的方法。

我试过下面的博客说:

https://blog.maskalik.com/entity-framework/2013/12/23/entity-framework-updating-database-from-detached-objects/

但工作不太好

[HttpPut]
public async Task<ActionResult> Put(Persona persona)
{
var user = await _userManager.GetUserAsync(HttpContext.User);

var oldpersona = await context.Personas.FindAsync(persona.PersonaId);

context.Entry(oldpersona).CurrentValues.SetValues(persona);
context.Entry(oldpersona).CurrentValues.SetValues(persona.Colonia);
context.Entry(oldpersona).CurrentValues.SetValues(persona.Municipio);
context.Entry(oldpersona).CurrentValues.SetValues(persona.Estado);          
await context.SaveChangesAsync(user.Id);
return NoContent();
}

我读到我可以使用.AsNoTracking((来不跟踪实体,但如果我需要跟踪它们,我会编辑它们。

这是我在控制器中的代码人员:

[HttpGet("{id}")]
public async Task<ActionResult<Persona>> Get(int id)
{
var persona = await context.Personas.Where(x => x.PersonaId == id)
.Include(x => x.Colonia)
.Include(x => x.Municipio)
.Include(x => x.Estado)
.FirstOrDefaultAsync();
if (persona == null) { return NotFound(); }
return persona;
}
[HttpPut]
public async Task<ActionResult> Put(Persona persona)
{
context.Attach(persona).State = EntityState.Modified;
await context.SaveChangesAsync();
return NoContent();
}

这是我的相关课程:

public class Persona
{
[Key]
public int PersonaId { get; set; }
public string Nombre { get; set; }
public string Ap_Paterno { get; set; }
public string Ap_Materno { get; set; }
public Sexo Sexo { get; set; }
public DateTime? FechadeNacimiento {get; set;}
public int Edad
{
get
{
DateTime now = DateTime.Today;
int Edad = DateTime.Today.Year - FechadeNacimiento.Value.Year;
if (DateTime.Today < FechadeNacimiento.Value.AddYears(Edad))
return --Edad;
else
return Edad;
}
}
public string Email { get; set; }
public string Telefono { get; set; }
public string Celular { get; set; }
[StringLength(12)]
public string Nss { get; set; }
[StringLength(18)]
public string Curp { get; set; }
[StringLength(13)]        
public string Rfc { get; set; }
public string Observaciones { get; set; }
public string Calle { get; set; }
public string Num_Ext { get; set; }
public string Num_Int { get; set; }
public int CodigoPostal { get; set; }        
public DateTime? FechaRegistro { get; set; }     
public bool Activo { get; set; }     
//propiedades de navegacion
public int? ColoniaId { get; set; }
public virtual Colonia Colonia { get; set; }
public int? MunicipioId { get; set; }
public virtual Municipio Municipio { get; set; }
public int? EstadoId { get; set; }
public virtual Estado Estado { get; set; }
}   
public enum Sexo
{
Masculino,
Femenino,
Indefinido
}

public class Estado
{
[Key]
public int EstadoId { get; set; }
[Required(ErrorMessage = "El campo {0} es requerido")]
public string Nombre { get; set; }
public DateTime? FechaRegistro { get; set; }
public bool Activo { get; set; }/
//propiedades de navegacion        
public int ZonaId{ get; set; }
public virtual Zona Zona { get; set; }        
}

public class Municipio
{
[Key]
public int MunicipioId { get; set; }
[Required(ErrorMessage = "El campo {0} es requerido")]
public string Nombre { get; set; }
public DateTime? FechaRegistro { get; set; }
public bool Activo { get; set; }
//propiedades de navegacion      
public int EstadoId { get; set; }
public virtual Estado Estado { get; set; }
}
public class Colonia
{
[Key]
public int ColoniaId { get; set; }
[Required(ErrorMessage = "El campo {0} es requerido")]
public int CodigoPostal { get; set; }
public Asentamiento Asentamiento { get; set; }
[Required(ErrorMessage = "El campo {0} es requerido")]
public string NombreColonia { get; set; }       
public DateTime? FechaRegistro { get; set; }
public bool Activo { get; set; }
//propiedades de navegacion       
public int MunicipioId { get; set; }
public virtual Municipio Municipio { get; set; }
public int EstadoId { get; set; }
public virtual Estado Estado { get; set; }
}
public enum Asentamiento
{
Colonia,
Fraccionamiento,
Condominio,
[Display(Name = "Unidad habitacional")]
Unidadhabitacional,
Barrio,
Equipamiento,
[Display(Name = "Zona comercial")]
Zonacomercial,
Rancho,
Rancheria,
[Display(Name = "Parque industrial")]
Parqueindustrial,
Granja,
Pueblo,
Ejido,
[Display(Name = " Zona federal")]
Zonafederal,
Aeropuerto,
Hacienda,
Paraje
}

我想问题是,当我进行包括时,在市政府内部,它将州和殖民地纳入其中,这就是为什么EF不止一次跟踪这些实体,但我该如何解决它?

var person=等待上下文。People.Where(x=>x.PersonId==id(.Include(x=>x.Colony(.包括(x=>x.市政府(.Include(x=>x.Status(.FirstOrDefaultAsync((;

没有这样的方法:

var person=等待上下文。People.Where(x=>x.PersonId==id(.Include(x=>x.Colony(.Include(x=>x.Municipal(.TheIninclude(x=>x.State(.AsNoTracking((.Include(x=>x.Status(.FirstOrDefaultAsync((;if(person==null({return NotFound((;}返回人员;

这样在市政府中,它就不会跟踪其内部的实体,在这种情况下,它不会干扰该州,包括我已经有

编辑具有导航属性的实体的最佳方式是什么??

我也看到他们使用Detach,但我真的不知道如何在我的代码中使用它。

Entry<Persona>(persona).State = EntityState.Detached;

只需尝试此

[HttpPut]
public async Task<ActionResult> Put(Persona persona)
{
var existedPersona = await context.Personas.Where(x => x.PersonaId == persona.PersonaId)
.FirstOrDefaultAsync();
if (existedPersona == null) { return NotFound(); }
context.Entry(existedPersona).CurrentValues.SetValues(persona);
await context.SaveChangesAsync();
return NoContent();
}

如果你在导航属性中也有一些更新,那么包括它们

var existedPersona = await context.Personas.Where(x => x.PersonaId == id)
.Include(x => x.Colonia)
.Include(x => x.Municipio)
.Include(x => x.Estado)
.FirstOrDefaultAsync();

最新更新