ASP.NET Core MVC视图中关联数据访问报错问题排查
问题背景
在ASP.NET Core MVC视图中无法正确访问关联数据,推测与集合型、引用型导航属性有关,但无法定位具体原因。该应用用于跟踪原型测试,Test与Prototype实体为一对多关系。
实体模型代码
Test模型(已移除部分属性)
public int Test_ID { get; set; } public string Test_Name { get; set; } public string? Test_Procedure { get; set; } public string? Test_Notes { get; set; } public ICollection<Prototype>? Prototype{ get; set; }
Prototype模型
public int Prototype_ID { get; set; } public string Prototype_Name { get; set; } public string Prototype_Model { get; set; } public int Trials { get; set; } public Test Test { get; set; }
控制器代码(PrototypeController.cs)
public async Task<IActionResult> Index(int? id) { var test = _db.Tests .AsNoTracking() .Include(t => t.Prototypes); return View(await test.ToListAsync()); }
视图代码
@model IEnumerable<TortureChamber.Models.Test> ... <tbody> @foreach (var test in Model) { <tr> <td width="25%">@test.Test_Name</td> @*Below is where my errors are*@ <td width="25%">@test.Prototypes.Prototype_Name</td> <td width="25%">@test.Prototypes.Prototype_Model</td> <td width="25%">@test.Prototypes.Cycles</td> </tr> } </tbody>
错误信息
CS1061 'ICollection' does not contain a definition for 'Prototype_Name' and no accessible extension method 'Prototype_Name' accepting a first argument of type 'ICollection' could be found (are you missing a using directive or an assembly reference?)
问题原因及解决方法
导航属性名称不匹配:Test模型中定义的集合导航属性是
Prototype(单数),但控制器Include时写的是t.Prototypes(复数),EF Core无法正确识别并加载关联数据。建议将Test模型中的属性改为复数形式,符合集合命名规范:public ICollection<Prototype>? Prototypes { get; set; }集合属性不能直接访问单个实体属性:
Prototypes是ICollection<Prototype>类型,属于集合,不能直接通过@test.Prototypes.Prototype_Name访问单个Prototype的属性。因为一个Test对应多个Prototype,需要在视图中嵌套循环遍历每个Test下的Prototypes:
修改后的视图代码:<tbody> @foreach (var test in Model) { @* 遍历当前Test的所有关联原型 *@ foreach (var prototype in test.Prototypes ?? Enumerable.Empty<Prototype>()) { <tr> <td width="25%">@test.Test_Name</td> <td width="25%">@prototype.Prototype_Name</td> <td width="25%">@prototype.Prototype_Model</td> <td width="25%">@prototype.Trials</td> </tr> } @* 处理无关联原型的情况 *@ if (test.Prototypes == null || !test.Prototypes.Any()) { <tr> <td width="25%">@test.Test_Name</td> <td colspan="3">无关联原型</td> </tr> } } </tbody>空值处理:由于
Prototypes是可空集合,遍历前需做空值判断,使用test.Prototypes ?? Enumerable.Empty<Prototype>()确保即使集合为null也能安全遍历,避免空引用异常。属性名错误修正:原视图中使用了
@test.Prototypes.Cycles,但Prototype模型中对应的属性是Trials,需修正为@prototype.Trials。
内容的提问来源于stack exchange,提问作者chefjeff98

