繁体   English   中英

具有多对多关系的实体框架核心返回对象

[英]Entity Framework Core returning object with many to many relationship

我不确定如何将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/zh-cn/ef/core/querying/related-data ),但是我不知道该如何进一步返回对象和标签。

您的问题是由循环引用引起的,您可以尝试在下面忽略循环引用。

            services.AddMvc()
                .AddJsonOptions(opt => {
                    opt.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
                });

对于另一个选项,您可以尝试直接使用List<Tag>而不是List<ObjectTag>返回ObjectModel

ObjectModel

    public partial class ObjectModel
{
    public int ObjectId { get; set; }
    public string Name { get; set; }
    public virtual List<Tag> Tags { get; set; }
}

询问

        public List<Models.ObjectModel> GetAll()
    {
        //return _db.Object
        //    .Include(o => o.ObjectTags)
        //    .ThenInclude(ot => ot.Tag)
        //    .ToList();
        return _db.Object
            .Include(o => o.ObjectTags)
            .ThenInclude(ot => ot.Tag)
            .Select(r => new Models.ObjectModel
            {
                ObjectId = r.ObjectId,
                Name = r.Name,
                Tags = r.ObjectTags.Select(ot => ot.Tag).ToList()
            })
            .ToList();
    }

如果在查询中使用“ Include或“ Theninclude Include ,它将创建循环引用。 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 ,则不需要使用IncludeTheninclude

希望它现在能按预期工作!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM