【问题标题】:Post request with many-to-many relation具有多对多关系的发布请求
【发布时间】:2021-06-02 13:27:08
【问题描述】:

我想向我的 API 发送一个包含关系的发布请求,例如:

{
"name": "test",
"description": "test",
"releaseDate": "0001-01-01T00:20:40",
"publisherId": 1
}

其中 publisherId 是外部 id。 我可以让它适用于一对多的关系,但不是多对多。 这是我现在的模型:

public class Game
{
    [Required]
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public DateTime ReleaseDate { get; set; }

    public int? PublisherId { get; set; }
    public ICollection<int> DeveloperIds { get; set; }
    public ICollection<int> CategoryIds { get; set; }
    public ICollection<int> PlatformIds { get; set; }

    [InverseProperty("PublishedGames")]
    [ForeignKey("PublisherId")]
    public virtual Company Publisher { get; set; }
    [ForeignKey("DeveloperIds")]
    public virtual ICollection<GameCompany> Developers { get; set; }
    [ForeignKey("CategoryIds")]
    public virtual ICollection<GameCategory> Categories { get; set; }
    [ForeignKey("PlatformIds")]
    public virtual ICollection<GamePlatform> Platforms { get; set; }
}

但我无法将它添加到模型中...

    [ForeignKey("DeveloperIds")]
    public virtual ICollection<GameCompany> Developers { get; set; }

这个错误是不言自明的,但我不知道这些建议是否正确。

System.InvalidOperationException H结果=0x80131509 Message=无法映射属性“Game.DeveloperIds”,因为它属于“ICollection”类型,不是受支持的原始类型或有效的实体类型。显式映射此属性,或使用“[NotMapped]”属性或使用“OnModelCreating”中的“EntityTypeBuilder.Ignore”忽略它。

我也尝试过其他类型,如 IEnumerableIListList 和数组,但没有成功。 我该如何解决这个问题?提前致谢

我也不能使用 .NET 5,因为谷歌应用引擎不支持。

编辑: GameCompany 类:

public class GameCompany
{
    public int GameId { get; set; }
    public Game Game { get; set; }
    public int CompanyId { get; set; }
    public Company Company { get; set; }
}

游戏控制器:

    [HttpPost]
    public ActionResult<GameRepresentation> CreateGame([FromBody] Game newGame)
    {

        context.Games.Add(newGame);
        context.SaveChanges();

        var game = context.Games
              .Include("Platforms")
              .Include("Categories")
              .Include("Developers")
              .Include("Publisher")
              .Single(br => br.Id == newGame.Id);

        List<int> PlatformIds = new List<int>();
        foreach (GamePlatform platform in game.Platforms)
        {
            PlatformIds.Add(platform.PlatformId);
        }
        List<int> CategoryIds = new List<int>();
        foreach (GameCategory category in game.Categories)
        {
            CategoryIds.Add(category.CategoryId);
        }
        List<int> DeveloperIds = new List<int>();
        foreach (GameCompany developer in game.Developers)
        {
            DeveloperIds.Add(developer.CompanyId);
        }

        var toReturn = new GameRepresentation
        {
            Id = game.Id,
            Name = game.Name,
            Description = game.Description,
            ReleaseDate = game.ReleaseDate,

            PublisherId = game.Publisher?.Id,
            PublisherName = game.Publisher?.Name,

            PlatformIds = PlatformIds,
            CategoryIds = CategoryIds,
            DeveloperIds = DeveloperIds
        };
        return Created("" ,toReturn);
    }

【问题讨论】:

  • 你能显示GameCompany类吗?
  • @Serge 添加到原帖
  • 你用的是什么版本的网络?
  • 使用 .NET Core 3.1

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


【解决方案1】:

你将不得不改变你的模型

public class Game
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public DateTime ReleaseDate { get; set; }

    
    // public virtual ICollection<Company> Companies { get; set; }
     [InverseProperty(nameof(GameCompany.Game))]
    public virtual ICollection<GameCompany> Developers { get; set; }
  
}
public class Company
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
  
     //public virtual ICollection<Game> Games { get; set; }
  [InverseProperty(nameof(GameCompany.Company))]
    public virtual ICollection<GameCompany> Developers { get; set; }
  
}

public GameCompany
{
[Key]
 public int Id { get; set; }
[ForeignKey(nameof(CompanyId))]
[InverseProperty("Developers")]
public int GameId { get; set; }
 public virtual Game Game{ get; set; }
 
 public int CompanyId { get; set; }
[ForeignKey(nameof(CompanyId))]
[InverseProperty(nameof(Company.Developers))]
public virtual Company Publisher{ get; set; }
}

和数据库上下文

modelBuilder.Entity<GameCompany>(entity =>
            {
                entity.HasOne(d => d.Game)
                    .WithMany(p => p.GameCompany)
                    .HasForeignKey(d => d.GameId)
                    .OnDelete(DeleteBehavior.ClientSetNull);
                  

                entity.HasOne(d => d.Company)
                    .WithMany(p => p.GameCompany)
                    .HasForeignKey(d => d.CompanyId);
                   
            });

更新

由于您根据我的回答发布了新的更新和更正的代码,请通过添加 [NotMapped] 来修复这些问题

[NotMapped]
public ICollection<int> DeveloperIds { get; set; }
[NotMapped]
public ICollection<int> CategoryIds { get; set; }
[NotMapped]
 public ICollection<int> PlatformIds { get; set; }

【讨论】:

  • 那么我该如何处理我的控制器中的post请求,例如,我在这部分使用什么类型:CreateGame([FromBody] Game newGame)
  • 请发布整个动作
  • 我在你的游戏类中看不到任何平台和类别
  • 而且你必须更新到Net5,否则选择游戏代码会更复杂。
  • 我更新了游戏类,但我无法使用 .NET 5,因为我必须将其部署到不支持 .NET 5 的谷歌云应用引擎
【解决方案2】:

我不知道这是否是理想的解决方案,但我通过手动创建加入实体“GameCompany”来实现它(其他实体也是如此)

控制器:

    [HttpPost]
    public ActionResult<GameRepresentation> CreateGame([FromBody] Game gameFromBody)
    {
        context.Games.Add(gameFromBody);
        context.SaveChanges();
        var publisher = context.Companies.Single(b => b.Id == gameFromBody.PublisherId);
        ICollection<GameCompany> developers = new List<GameCompany>();
        foreach (var developerId in gameFromBody.DeveloperIds)
        {
            var Company = context.Companies.Single(b => b.Id == developerId);
            developers.Add(new GameCompany()
            {
                GameId = gameFromBody.Id,
                Game = gameFromBody,
                CompanyId = developerId,
                Company = context.Companies.Single(b => b.Id == developerId)
            });
        }
        ICollection<GamePlatform> platforms = new List<GamePlatform>();
        foreach (var platformId in gameFromBody.PlatformIds)
        {
            platforms.Add(new GamePlatform()
            {
                GameId = gameFromBody.Id,
                Game = gameFromBody,
                PlatformId = platformId,
                Platform = context.Platforms.Single(b => b.Id == platformId)
            });
        }
        ICollection<GameCategory> categories = new List<GameCategory>();
        foreach (var categoryId in gameFromBody.CategoryIds)
        {
            categories.Add(new GameCategory()
            {
                GameId = gameFromBody.Id,
                Game = gameFromBody,
                CategoryId = categoryId,
                Category = context.Categories.Single(b => b.Id == categoryId)
            });
        }

        gameFromBody.Categories = categories;
        gameFromBody.Developers = developers;
        gameFromBody.Platforms = platforms;
        context.SaveChanges();

        return Created("", gameFromBody);
    }

型号:

public class Game
{
    [Required]
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public DateTime ReleaseDate { get; set; }

    public int? PublisherId { get; set; }
    [NotMapped]
    public ICollection<int> DeveloperIds { get; set; }
    [NotMapped]
    public ICollection<int> CategoryIds { get; set; }
    [NotMapped]
    public ICollection<int> PlatformIds { get; set; }

    [InverseProperty("PublishedGames")]
    [ForeignKey("PublisherId")]
    public virtual Company Publisher { get; set; }
    public virtual ICollection<GameCompany> Developers { get; set; }
    public virtual ICollection<GameCategory> Categories { get; set; }
    public virtual ICollection<GamePlatform> Platforms { get; set; }
}

public class Company
{
    [Required]
    public int Id { get; set; }
    [Required]
    public string Name { get; set; }
    public string Description { get; set; }
    public virtual ICollection<Game> PublishedGames { get; set; }
    public virtual ICollection<GameCompany> DevelopedGames { get; set; }
}

public class GameCompany
{
    public int GameId { get; set; }
    public virtual Game Game { get; set; }
    public int CompanyId { get; set; }
    public virtual Company Company { get; set; }
}

【讨论】:

    猜你喜欢
    • 2019-08-08
    • 1970-01-01
    • 2019-01-29
    • 1970-01-01
    • 2022-12-01
    • 2020-11-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-21
    相关资源
    最近更新 更多