【问题标题】:EF Core how to create relational modelEF Core 如何创建关系模型
【发布时间】:2019-02-09 20:53:47
【问题描述】:

我是 Asp.Net Core 的初学者,我需要做以下事情:

我有模型cursounidade,它们共享多对多关系。

两种模型都可以自己正常工作,但是我的问题是我无法制作关系模型。

这个想法是创建一个端点来接收一个带有一个unidade 和一个curso 数组的对象,API 会相应地添加或删除关系。

以下代码是我目前所做的,我收到一个错误Identity_Insert

我的方向是否正确?或者还有其他更好的方法吗?

Modelo de curso
public class Curso
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Required]
    [Key]        
    public long curId { get; set; }

    [Required]
    [StringLength(80)]
    public string curDescricao { get; set; }

    [Required]
    [StringLength(1)]
    public string curStatus { get; set; }

    [StringLength(20)]
    public string curCodExterno { get; set; }

    [StringLength(60)]
    public string curObservacao { get; set; }
}

Modelo de unidade
public class Unidade
{        
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Required]
    [Key]
    public long uniId { get; set; }
    [Required]
    [StringLength(80)]        
    public string uniDescricao { get; set; }
    [Required]
    [StringLength(1)]
    public string uniStatus { get; set; }
    [StringLength(20)]
    public string uniCodExterno { get; set; }
    public byte[] uniImagem { get; set; }
}

Modelo de CursoUnidade
public class CursoUnidade
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Required]
    [Key]
    public long cuuId { get; set; }

    /*[Required]        
    public long cuuCurId { get; set; }
    [ForeignKey("cuuCurId")]*/        
    public List<Curso> Curso { get; set; }

    /*[Required]
    public long cuuUniId { get; set; }
    [ForeignKey("cuuUniId")]        */
    public Unidade Unidade { get; set; }
}

Serviço de unidade
public void AddTeste(CursoUnidade cursoUnidade)
{
    _contexto.Add(cursoUnidade);
    _contexto.SaveChanges();
}

【问题讨论】:

  • 你是如何实例化 cursoUnidade 的?它有什么价值?请粘贴确切的错误。

标签: c# entity-framework asp.net-core-webapi


【解决方案1】:

问题是 CursoUnidade 上传入的 CursoUnidade 实例没有被 EF 跟踪。因此,当您尝试添加并保存时,它会尝试再次创建这两个实体。但是,由于它们都已经有 id,所以它不能这样做并且会失败。

这是与尝试直接保存传递给您的操作的内容相关的众多问题之一。您应该使用视图模型,然后将其映射到您最终保存的实际实体上。这迫使您明确说明自己在做什么,从而减少诸如此类的错误。此外,除非您实际上希望两个相关实例能够在它们关联的同时进行修改,否则发布整个实体是没有意义的。这很容易导致 overpost 漏洞利用,即用户对他们不应该修改的实体进行修改,并且由于 post 服务器端的草率处理,这些只是被盲目地保存到数据库中。

改为使用视图模型/DTO,例如:

public class CursoUnidadeDTO
{
    public long CursoId { get; set; }
    public long UnidadeId { get; set; }
}

那么,在你的行动中:

public void AddTeste(CursoUnidadeDTO cursoUnidade)
{
    var curso = await _contexto.Cursos.FindAsync(cursoUnidade.CursoId);
    var unidade = await _contexto.Unidades.FindAsync(cursoUnidade.UnidadeId);
    if (curso == null || unidade == null)
    {
        return BadRequest("Cannot create relationship");
    }

    _contexto.Add(new CursoUnidade { Curso = curso, Unidade = unidade });
    await _contexto.SaveChangesAsync();
}

或者,如果您的 CursoUnidade 类具有明确的外键属性,您甚至不需要查找任何内容:

_contexto.Add(new CursoUnidade { CursoId = cursoUnidade.CursoId, UnidadeId = cursoUnidade.UnidadeId });

或者,您可以先简单地附加这些实体,以便 EF 知道它们:

_contexto.Attach(cursoUnidade.Curso);
_contexto.Attach(cursoUnidade.Unidade);
_contexto.Add(cursoUnidade);
await _contexto.SaveChangesAsync();

这将解决您当前的问题,但就像我之前所说的,它也会允许过度发布,如果这不是您明确允许的,可能会非常危险。

【讨论】:

  • 它有效,非常好,但是既然你说这种方法可能很危险,我还有什么其他方法可以安全地实现同样的关系目标?
  • 使用我的回答中首先提到的视图模型/DTO。
猜你喜欢
  • 1970-01-01
  • 2021-03-01
  • 2018-05-01
  • 1970-01-01
  • 2021-05-08
  • 1970-01-01
  • 2021-11-17
  • 1970-01-01
  • 2017-04-17
相关资源
最近更新 更多