我不确定如何将EF Core与.NET Core应用程序一起使用来获取所需的信息。我有两个数据库表-具有多对多关系的OBJECTS和TAGS(使用第三个联接表OBJECTTAGS)。我想获取所有对象(大约1400个)及其关联的标签。
这是我的三个模型:
using System;
using System.Collections.Generic;
namespace ContentMarketplace.Models
{
public partial class Object
{
public int ObjectId { get; set; }
...
public virtual List<ObjectTag> ObjectTags { get; set; }
}
}
namespace ContentMarketplace.Models
{
public partial class Tag
{
public int TagId { get; set; }
...
public virtual List<ObjectTag> ObjectTags { get; set; }
}
}
namespace ContentMarketplace.Models
{
public partial class ObjectTag
{
public int ObjectId { get; set; }
public virtual Object Object { get; set; }
public int TagId { get; set; }
public virtual Tag Tag { get; set; }
}
}
这就是我上下文中的OnModelCreating()方法中的内容:
modelBuilder.Entity<ObjectTag>(entity =>
{
entity.HasKey(e => new { e.ObjectId, e.TagId });
entity.HasOne(ot => ot.Object)
.WithMany(o => o.ObjectTags)
.HasForeignKey(ot => ot.ObjectId);
entity.HasOne(ot => ot.Tag)
.WithMany(t => t.ObjectTags)
.HasForeignKey(ot => ot.TagId);
});
当我尝试在ObjectController.cs中返回数据时会出现此问题
namespace ContentMarketplace.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ObjectController : ControllerBase
{
private readonly ContentMarketplaceContext _context;
public ObjectController(ContentMarketplaceContext context)
{
_context = context;
}
[HttpGet]
public ActionResult<List<ContentMarketplace.Models.Object>> GetAll()
{
return _context.Objects
.Include(o => o.ObjectTags)
.ThenInclude(ot => ot.Tag)
.ToList();
}
}
}
Include()。ThenInclude()创建一个循环关系,其中HTTP请求不仅返回与每个对象关联的标签信息,而且还返回与每个标签相关的所有对象,依此类推,从而使浏览器崩溃。
如果我取出ThenInclude()可以正常工作,但不会返回不在我的ObjectTag模型中的所有标签信息。
我知道这与上下文中已经存在的EF Core自动加载有关(例如https://docs.microsoft.com/en-us/ef/core/querying/related-data中的“提示”注释),但是我不知道如何在不包含以下内容的情况下返回对象和标签再进一步。
答案 0 :(得分:0)
您的问题是由循环引用引起的,您可以在下面尝试忽略循环引用。
services.AddMvc()
.AddJsonOptions(opt => {
opt.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
对于另一种选择,您可以尝试直接返回ObjectModel
而不是List<Tag>
的{{1}}
List<ObjectTag>
ObjectModel
查询
public partial class ObjectModel
{
public int ObjectId { get; set; }
public string Name { get; set; }
public virtual List<Tag> Tags { get; set; }
}
答案 1 :(得分:0)
如果在查询中使用Include
或Theninclude
,则会创建循环引用。 JSON无法处理循环引用。您可以使用Select
查询轻松解决此问题。
没有DTO:
编写您的GetAll()
控制器方法,如下所示:
[HttpGet]
public IActionResult GetAll()
{
var objectList = _context.Objects.Select(o => new
{
o.ObjectId,
Tags = o.ObjectTags.Select(ot => ot.Tag).ToList()
}).ToList();
return Ok(objectList);
}
使用DTO:
按如下所示编写DTO类:
public class ObjectDto
{
public int ObjectId { get; set; }
....
public List<Tag> Tags { get; set; }
}
然后,您的GetAll()
控制器方法应如下:
[HttpGet]
public ActionResult<List<ObjectDto>> GetAll()
{
var objectList = _context.Objects.Select(o => new ObjectDto
{
ObjectId = o.ObjectId,
Tags = o.ObjectTags.Select(ot => ot.Tag).ToList()
}).ToList();
return objectList;
}
注意:如果您在查询中使用Select
,则无需使用Include
或Theninclude
。
希望它现在可以正常运行!