在ASP的世界里肯定是新的,在下面的例子中发现自己迷失了。显然需要专家来引导。
有两个模特团队&具有以下数据库结构的锦标赛:
public class Tournament
{
[Key]
public string TournamentID { get; set; }
public DateTime TournamentDate { get; set; }
public string Place { get; set; }
[ForeignKey("TeamA")]
public string TeamAID { get; set; }
public Team TeamA { get; set; }
[ForeignKey("TeamB")]
public string TeamBID { get; set; }
public Team TeamB { get; set; }
}
public class Team
{
[Key]
public string TeamID { get; set; }
public string TeamName { get; set; }
public string Captain { get; set; }
[InverseProperty("TeamA")]
public virtual ICollection<Tournament> TeamA { get; set; }
[InverseProperty("TeamB")]
public virtual ICollection<Tournament> TeamB { get; set; }
}
因为锦标赛有两个小组因此使用InverseProperty和外键来建立关系。
然而,因为我试图将结果带回来:
团队详情;
以下列格式显示竞争对手的锦标赛列表:
TeamID
TeamName
CaptainName
TournamentID | TournamentDate | TournamentPlace |竞争者
...
...
...
因此,使用如下的辅助模型:
public class TeamVM
{
public string ID { get; set; }
public string Name { get; set; }
public string Captain { get; set; }
public virtual IEnumerable<TournamentVM> Tournaments { get; set; }
}
public class TournamentVM
{
public string ID { get; set; }
public DateTime Date { get; set; }
public string Place { get; set; }
public string Competitor { get; set; }
}
并使用如下控制器映射数据库相关表中的值:
public async Task<IActionResult> TheAction(string id)
{
Team team = await _context.Teams.Where(x => x.TeamID == id).Include(x => x.TeamA).Include(x => x.TeamB).SingleOrDefaultAsync();
TeamVM model = new TeamVM
{
ID = team.TeamID,
Name = team.TeamName,
Captain = team.Captain,
Tournaments = team.TeamA.Where(x => x.TeamAID == team.TeamID).Select(x => new TournamentVM
{
ID = x.TournamentID,
Date = x.TournamentDate,
Place = x.Place,
Competitor = x.TeamB.TeamName
}).Concat(team.TeamB.Where(x => x.TeamBID == team.TeamID).Select(x => new TournamentVM
{
ID = x.TournamentID,
Date = x.TournamentDate,
Place = x.Place,
Competitor = x.TeamA.TeamName
})).OrderBy(x => x.Date)
};
return View(model);
}
但结果却是抱怨:
NullReferenceException:对象引用未设置为对象的实例。
因此突出显示部分:
Tournaments = team.TeamA.Where(x => x.TeamAID == team.TeamID).Select(x => new TournamentVM
{
ID = x.TournamentID,
Date = x.TournamentDate,
Place = x.Place,
Competitor = x.TeamB.TeamName
}).Concat(team.TeamB.Where(x => x.TeamBID == team.TeamID).Select(x => new TournamentVM
{
ID = x.TournamentID,
Date = x.TournamentDate,
Place = x.Place,
Competitor = x.TeamA.TeamName
})).OrderBy(x => x.Date)
尝试了相当多的时间终于让我发现,当发生上述错误时,如果我将上述部分修改为:
Tournaments = team.TeamA.Where(x => x.TeamAID == team.TeamID).Select(x => new TournamentVM
{
ID = x.TournamentID,
Date = x.TournamentDate,
Place = x.Place,
Competitor = x.TeamA.TeamName //i.e. TeamA instead of TeamB
}).Concat(team.TeamB.Where(x => x.TeamBID == team.TeamID).Select(x => new TournamentVM
{
ID = x.TournamentID,
Date = x.TournamentDate,
Place = x.Place,
Competitor = x.TeamB.TeamName //i.e. TeamB instead of TeamA
})).OrderBy(x => x.Date)
结果显示。
因此,我不能只提供参赛者的名字,而只能提供球队自己的名字。换句话说,TeamA的部分无法为竞争对手提供TeamB.TeamName。
可能是什么原因和解决办法?
对视图使用以下代码:
@model TeamVM
<div>@Model.ID</div>
<div>@Model.Name</div>
<div>@Model.Captain</div>
<table>
<thead>
<tr>
<th>ID</th>
<th>Date</th>
<th>Place</th>
<th>Competitor</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Tournaments)
{
<tr>
<td>@item.ID</td>
<td>@item.Date</td>
<td>@item.Place</td>
<td>@item.Competitor</td>
</tr>
}
</tbody>
</table>
期待并感谢您的专业意见。
提前致谢。
答案 0 :(得分:0)
我想建议另一种方法来解决这个问题,因为你的设置听起来有点令人困惑。
您可以简化:
//The same
public class Tournament
{
[Key]
public string TournamentID { get; set; }
public DateTime TournamentDate { get; set; }
public string Place { get; set; }
[ForeignKey("TeamA")]
public string TeamAID { get; set; }
public Team TeamA { get; set; }
[ForeignKey("TeamB")]
public string TeamBID { get; set; }
public Team TeamB { get; set; }
}
public class Team
{
[Key]
public string TeamID { get; set; }
public string TeamName { get; set; }
public string Captain { get; set; }
//Instead of these two
//[InverseProperty("TeamA")]
//public virtual ICollection<Tournament> TeamA { get; set; }
//[InverseProperty("TeamB")]
//public virtual ICollection<Tournament> TeamB { get; set; }
//Let's just include the tournaments this team participated in
public virtual ICollection<Tournament> Tournaments { get; set; }
}
现在,您可以使用Tournaments
拨打Include()
。
public async Task<IActionResult> TheAction(string id)
{
Team team = await _context.Teams.SingleOrDefaultAsync(x => x.TeamID == id).Include(t => t.Tournaments);
//You should be able to eager load the teams at this point since you don't use virtual, put a break point to check. If not, you can load them using .ThenInclude()
TeamVM model = new TeamVM
{
ID = team.TeamID,
Name = team.TeamName,
Captain = team.Captain,
Tournaments = team.Tournaments.Select(tournament => new TournamentVM()
{
ID = tournament.TournamentID,
Date = tournament.TournamentDate,
Place = tournament.Place,
Competitor = (tournament.TeamA == team) ? tournament.TeamB.Name : tournament.TeamA.TeamName
//pick the other team as competitor
}).OrderBy(x => x.Date)
};
return View(model);
}
我自己没有测试过代码,所以欢迎您将其视为伪代码。让我知道结果。
答案 1 :(得分:0)
雅虎!
最后,我确实找到了解决方案。
哇!这个ASP核心世界太棒了!
感谢@Mithgroth的建议,但不能偏离数据库模型。但是,如果可以建议任何进一步的干净版本,我将非常感谢,只要数据库结构保持不变。
无论如何,我在24小时后完成的解决方案是更新的控制器操作,如下所示,其余部分继续保持不变:
public async Task<IActionResult> TheAction(string id){
Team team = await _context.Teams.Where(x => x.TeamID == id).Include(x => x.TeamA).Include(x => x.TeamB).SingleOrDefaultAsync();
var gamesList = (from x in _context.Tournaments
.Where(x => x.TeamAID == id || x.TeamBID == id)
select new TournamentVM
{
ID = x.TournamentID,
Date = x.TournamentDate,
Place = x.Place,
Competitor = x.TeamAID == id ? x.TeamB.TeamName : x.TeamA.TeamName
});
TeamVM model = new TeamVM
{
ID = team.TeamID,
Name = team.TeamName,
Captain = team.Captain,
Tournaments = from x in gamesList
.Select(x => new TournamentVM
{
ID = x.ID,
Date = x.Date,
Place = x.Place,
Competitor = x.Competitor
}).OrderBy(x => x.Date) select x
};
return View("TheAxion", model);}
: - )