繁体   English   中英

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

[英]How Working With Entity Framework Detached Objects?

你好社区我一直在努力解决这个问题很长一段时间,我正在使用blazor webassembly,do.net core和EntityFramework,我想更新我个人object的数据,这个object包含相关数据,neighborhood,municipality和state,如果我只更新这个人 object 如果它更新它会很好地工作,但是如果在查询中我包含带有 inlcude 的导航属性它不再更新导航属性

错误:

System.InvalidOperationException:无法跟踪实体类型“Status”的实例,因为已跟踪另一个具有与 {'StatusId'} 相同键值的实例。 附加现有实体时,确保只附加一个具有给定键值的实体实例。

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

我尝试了以下博客所说的内容:

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() 来不跟踪实体,但如果我需要跟踪它们,我将编辑它们。

这是我在 controller 人中的代码:

 [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
    }

我想问题是,当我执行包含时,在市政当局内部它带来了 state 并且在殖民地内部带来了 state 和市政当局,这就是为什么 EF 不止一次跟踪这些实体,但我该如何解决呢?

var person = await context.People.Where(x => x.PersonId == id).Include(x => x.Colony).Include(x => x.Municipality).包括(x => x.Status) .FirstOrDefaultAsync();

没有办法做这样的事情:

var person = await context.People.Where(x => x.PersonId == id).Include(x => x.Colony).包括(x => x.Municipality).ThenInclude(x=>x.State) .AsNoTracking().Include(x => x.Status).FirstOrDefaultAsync(); 如果(人 == null){ 返回 NotFound(); } 返回人;

因此在市政当局中,它不会跟踪其中的实体,在这种情况下为 state,并且不会干扰我已经拥有的 state 包含

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

我还看到他们使用 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();

暂无
暂无

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

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