简体   繁体   English

EF Core如何建立关系模型

[英]EF Core how to create relational model

I'm a beginner on Asp.Net Core and I need to do de following: 我是Asp.Net Core的初学者,我需要执行以下操作:

I have the models curso and unidade , they share a many to many relationship. 我有cursounidade的模特,他们有很多对很多的关系。

Both models work fine by themselves, my problem however is that I can't make the relational model. 两种模型本身都能很好地工作,但是我的问题是我无法建立关系模型。

The idea is to make an endpoint that receives an object with one unidade and an array of curso and the API would add or remove the relationships accordingly. 这个想法是使一个端点接收一个具有一个unidade和一组curso的对象,并且API将相应地添加或删除这些关系。

The following code is what I have made so far, I'm getting an error Identity_Insert . 到目前为止,以下代码是我所做的,但出现错误Identity_Insert

Am I on the right direction with this? 我在这个方向上正确吗? Or is there another proper better way of doing this? 还是有另一种合适的更好的方法呢?

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();
}

The problem is that the Curso and Unidade instances on the CursoUnidade that's being passed in are not being tracked by EF. 问题在于,EF不会跟踪传入的CursoUnidade上的CursoUnidade实例。 As a result, when you attempt to add it and save, it's attempting to create those two entities again. 结果,当您尝试添加和保存它时,它试图再次创建这两个实体。 However, since they both already have ids, it cannot do that and fails. 但是,由于它们都已经有ID,所以它不能这样做并且失败。

This is one of the many problems associated with trying to save what's passed into your action directly. 这是与尝试直接保存传递到操作中的内容有关的众多问题之一。 You should use a view model and then map that over the the actual entity you end up saving. 您应该使用视图模型,然后将其映射到最终保存的实际实体上。 This forces you to be explicit about what you're doing and results in less bugs such as this one. 这迫使您对正在做的事情保持清楚,并减少此类错误。 Also, unless you're actually intending the two related instances to be able to modified at the same time they're being associated, it doesn't make sense to post the entire entity, anyways. 另外,除非您实际上打算使两个相关实例能够在关联时同时进行修改,否则无论如何都没有必要发布整个实体。 This can easily lead to an overpost exploit, where the user makes modifications to entities they shouldn't be able to make, and because of the sloppy handling of the post server-side, those just get blindly saved to the database. 这很容易导致过度利用,用户对他们不应该进行的实体进行修改,并且由于对后期服务器端的处理不便,这些对象被盲目地保存到数据库中。

Instead, use a view model/DTO like: 而是使用如下视图模型/ DTO:

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

Then, in your action: 然后,在您的操作中:

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();
}

Or, if your CursoUnidade class had explicit foreign key properties, you wouldn't even need to look anything up: 或者,如果您的CursoUnidade类具有显式的外键属性,则您甚至不需要查找任何内容:

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

Alternatively, you can simply attach these entities first, so that EF knows about them: 或者,您可以简单地首先附加这些实体,以便EF知道它们:

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

That will solve your immediate issue, but like I said previously, it will also allow overposts, and if that's not something you're explicitly allowing, could be very dangerous. 这将解决您的当务之急,但是就像我之前说的那样,这也将允许超支,如果您未明确允许这样做,那将非常危险。

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

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