Asp.net 外键、即时加载和DTO(.NET Core 3.1/实体框架核心) 上下文

Asp.net 外键、即时加载和DTO(.NET Core 3.1/实体框架核心) 上下文,asp.net,.net,entity-framework,asp.net-core,entity-framework-core,Asp.net,.net,Entity Framework,Asp.net Core,Entity Framework Core,我正在构建一个简单的.NET核心API,从控制器返回正确的数据时遇到了一些问题。我预见到必须使用DTO来管理向API发送和从API发送的数据,但我不相信我已经正确配置了EF核心关系。让我陷入循环的是,我的模型中的子对象返回null——我将进一步解释。 我有两个域模型,Player和Match。每场比赛有四名球员,我相信这将需要为同一张表创建四个外键。EF Core生成的SQL数据库看起来正是我预想的样子——我已经包含了一个用于更多上下文的too。我可以使用API POST方法创建播放器对象。但

我正在构建一个简单的.NET核心API,从控制器返回正确的数据时遇到了一些问题。我预见到必须使用DTO来管理向API发送和从API发送的数据,但我不相信我已经正确配置了EF核心关系。让我陷入循环的是,我的模型中的子对象返回null——我将进一步解释。

我有两个域模型,Player和Match。每场比赛有四名球员,我相信这将需要为同一张表创建四个外键。EF Core生成的SQL数据库看起来正是我预想的样子——我已经包含了一个用于更多上下文的too。我可以使用API POST方法创建播放器对象。但是,当我使用Player guid(如下所示)创建Match对象时,从数据库查询新创建的Match对象并没有像我希望的那样返回JSON格式的Player对象;MatchController返回玩家GUID,但不返回玩家信息。

最终,我希望在一场比赛中始终显示四名球员中每名球员的球员数据,但我不确定要实现这一点,需要对我的模型或Fluent API进行哪些更改。我确实计划在将来使用AutoMapper将域模型对象映射到DTO模型对象,但目前的困境似乎是我应该首先解决的。如果还有其他可以提供更好帮助的信息,我将非常乐意提供更多信息!我们将真诚地感谢所有的帮助!提前谢谢

注意:我不在乎在我的播放器模型中有一组匹配项-我只包括了这些,因为我认为在Entity Framework Core中构建外键约束是必要的

模型: Player.cs(域模型)

公共类播放器
{
[关键]
公共Guid Id{get;set;}
[必需]
公共字符串名称{get;set;}
公共双重评级{get;set;}
已创建公共日期时间{get;set;}
公共日期时间已更新{get;set;}
公共ICollection matcheOne{get;set;}
公共ICollection MatchesTwo{get;set;}
公共ICollection匹配三个{get;set;}
公共ICollection匹配四个{get;set;}
}
Match.cs(域模型)

公共类匹配
{
[关键]
公共Guid Id{get;set;}
[必需]
public int TeamOneScore{get;set;}
[必需]
公共int TeamTwoScore{get;set;}
已创建公共日期时间{get;set;}
公共日期时间已更新{get;set;}
公共Guid播放器ID{get;set;}
公共Guid PlayerTwoId{get;set;}
公共Guid播放器第三个ID{get;set;}
公共Guid PlayerFourId{get;set;}
公共玩家玩家{get;set;}
公共玩家玩家两个{get;set;}
公共播放器播放三个{get;set;}
公共玩家玩家四个{get;set;}
}
ApplicationDbContext.cs(Fluent API)

模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
modelBuilder.Entity()
.Property(p=>p.Rating)
.HasDefaultValue(1000);
modelBuilder.Entity()
.Property(p=>p.Created)
.HasDefaultValueSql(“GETDATE()”);
modelBuilder.Entity()
.Property(p=>p.Updated)
.HasDefaultValueSql(“GETDATE()”);
modelBuilder.Entity()
.Property(m=>m.Created)
.HasDefaultValueSql(“GETDATE()”);
modelBuilder.Entity()
.Property(m=>m.Updated)
.HasDefaultValueSql(“GETDATE()”);
modelBuilder.Entity()
.HasMany(p=>p.MatchesOne)
.带一个(m=>m.PlayerOne)
.HasForeignKey(m=>m.playerId)
.OnDelete(DeleteBehavior.NoAction);
modelBuilder.Entity()
.HasMany(p=>p.MatchesTwo)
.带一个(m=>m.PlayerTwo)
.HasForeignKey(m=>m.PlayerTwoId)
.OnDelete(DeleteBehavior.NoAction);
modelBuilder.Entity()
.HasMany(p=>p.matchestree)
.带一个(m=>m.PlayerThree)
.HasForeignKey(m=>m.PlayerThreeId)
.OnDelete(DeleteBehavior.NoAction);
modelBuilder.Entity()
.HasMany(p=>p.MatchesFour)
.WithOne(m=>m.PlayerFour)
.HasForeignKey(m=>m.PlayerFourId)
.OnDelete(DeleteBehavior.NoAction);
}

控制器: PlayerController.cs

[HttpGet]
公共异步任务GetPlayers()
{
return wait_context.Players.toListSync();
}
[HttpPost]
公共异步任务后处理层(播放器)
{
_context.player.Add(player);
wait_context.SaveChangesAsync();
返回createDataAction(nameof(GetPlayer),new{id=player.id},player);
}
MatchController.cs

[HttpGet]
公共异步任务GetMatches()
{
return wait_context.Matches.toListSync();
}
[HttpPost]
公共异步任务后匹配(匹配)
{
_context.Matches.Add(匹配);
wait_context.SaveChangesAsync();
返回CreateDataAction(nameof(GetMatch),new{id=match.id},match);
}

HTTP请求 httppost:PostPlayer(/api/Player) 请求:

{
“姓名”:“迈克·布拉特”
}
答复:

{
“id”:“d3c022a2-d347-4a9a-d3ec-08d7b5480646”,
“姓名”:“迈克·布拉特”,
“评级”:1000,
“已创建”:“2020-02-19T14:32:48.803333”,
“更新”:“2020-02-19T14:32:48.803333”,
“matchesOne”:空,
“matchesTwo”:空,
“matchestree”:空,
“matchesFour”:空
}
HTTP-POST:PostMatch(/api/Match) 请求:

{
“TeamOneScore”:21,
“TeamTwoScore”:13,
“玩家ID”:“0589867f-590b-4344-d3e9-08d7b5480646”,
“playerWOID”:“0f45247b-1fdb-404a-d3ea-08d7b5480646”,
“PlayerThreeId”:“f8b4e13d-0dd0-4ef5-d3eb-08d7b54
[HttpGet]
public async Task<ActionResult<IEnumerable<Match>>> GetMatches()
{
    return await _context.Matches.ToListAsync();
}

// GET: api/Matches/5
[HttpGet("{id}")]
public async Task<ActionResult<Match>> GetMatch(Guid id)
{
    var match = await _context.Matches
                    .Include(m => m.PlayerOne)
                    .Include(m => m.PlayerTwo)
                    .Include(m => m.PlayerThree)
                    .Include(m => m.PlayerFour)
                    .Where(m => m.Id == id)
                    .FirstOrDefaultAsync();       
    return match;
}

[HttpPost]
public async Task<ActionResult<Match>> PostMatch(Match match)
{
    _context.Matches.Add(match);
    await _context.SaveChangesAsync();

    //change CreatedAtAction to CreatedAtAction...
    return RedirectToAction("GetMatch", new { id = match.Id }); 
}
{
    "id": "e35bff4e-1d3a-40db-6da7-08d7b5c7defc",
    "teamOneScore": 21,
    "teamTwoScore": 13,
    "created": "2020-02-20T13:43:54.1066667",
    "updated": "2020-02-20T13:43:54.1066667",
    "playerOneId": "6a35cfd0-b55f-4151-a75f-08d7b5c79d60",
    "playerTwoId": "caa71d4a-1fe5-488a-a760-08d7b5c79d60",
    "playerThreeId": "4c057f8c-9a05-4e33-a761-08d7b5c79d60",
    "playerFourId": "4dd619f2-1680-4bb6-a762-08d7b5c79d60",
    "playerOne": {
        "id": "6a35cfd0-b55f-4151-a75f-08d7b5c79d60",
        "name": "Mike Blart",
        "rating": 1000.0,
        "created": "2020-02-20T13:42:05.94",
        "updated": "2020-02-20T13:42:05.94",
        "matchesOne": [],
        "matchesTwo": null,
        "matchesThree": null,
        "matchesFour": null
    },
    "playerTwo": {
        "id": "caa71d4a-1fe5-488a-a760-08d7b5c79d60",
        "name": "aaa",
        "rating": 1000.0,
        "created": "2020-02-20T13:42:24.3866667",
        "updated": "2020-02-20T13:42:24.3866667",
        "matchesOne": null,
        "matchesTwo": [],
        "matchesThree": null,
        "matchesFour": null
    },
    "playerThree": {
        "id": "4c057f8c-9a05-4e33-a761-08d7b5c79d60",
        "name": "vvv",
        "rating": 1000.0,
        "created": "2020-02-20T13:42:28.83",
        "updated": "2020-02-20T13:42:28.83",
        "matchesOne": null,
        "matchesTwo": null,
        "matchesThree": [],
        "matchesFour": null
    },
    "playerFour": {
        "id": "4dd619f2-1680-4bb6-a762-08d7b5c79d60",
        "name": "ccc",
        "rating": 1000.0,
        "created": "2020-02-20T13:42:32.86",
        "updated": "2020-02-20T13:42:32.86",
        "matchesOne": null,
        "matchesTwo": null,
        "matchesThree": null,
        "matchesFour": []
    }
}
services.AddControllers().AddNewtonsoftJson(x =>
              x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);