【发布时间】:2020-03-07 16:56:12
【问题描述】:
我目前正在尝试以一对多的方式使用 EF Core(user 有很多 items)。一个或三个教程之后,我设法让两个非常小而简单的表工作起来;但是,我得到了一个json 异常:A possible object cycle was detected which is not supported,这表明我有循环引用。
这是我的代码,它使用 DTO 对象解决了这个问题,但是有没有更简洁的方法可以解决这个问题,因为虽然可以输入,但感觉有点错误。
用户:
namespace TestWebApplication.Database
{
public class User
{
[Key]
public int UserId { get; set; }
public string UserName { get; set; }
public string Dob { get; set; }
public string Location { get; set; }
public ICollection<Items> Items { get; set; }
}
}
项目:
namespace TestWebApplication.Database
{
public class Items
{
[Key]
public int ItemId { get; set; }
public string Item { get; set; }
public string Category { get; set; }
public string Type { get; set; }
public virtual User User { get; set; }
}
}
DtoItems:
namespace TestWebApplication.Database.DTOs
{
public class DtoItems
{
public string Item { get; set; }
public string Category { get; set; }
public string Type { get; set; }
public DtoUser User { get; set; }
}
}
DtoUser:
namespace TestWebApplication.Database.DTOs
{
public class DtoUser
{
public string UserName { get; set; }
public string Dob { get; set; }
public string Location { get; set; }
}
}
测试控制器:
[HttpGet]
[Route("getitems")]
public ActionResult<List<Items>> GetItems()
{
List<Items> items = _myContext.Items.Include(i => i.User).ToList();
// DTOs
List<DtoItems> dtoItems = new List<DtoItems>();
foreach (var i in items)
{
var dtoItem = new DtoItems
{
Item = i.Item,
Category = i.Category,
Type = i.Type,
User = new DtoUser
{
UserName = i.User.UserName,
Dob = i.User.Dob,
Location = i.User.Location
}
};
dtoItems.Add(dtoItem);
}
return Ok(dtoItems);
}
端点的输出:
[
{
"item": "xxx",
"category": "xxx",
"type": "xxx",
"user": {
"userName": "xxx",
"dob": "xxx",
"location": "xx"
}
},
{
"item": "xxx",
"category": "xxx",
"type": "xxx",
"user": {
"userName": "xxx",
"dob": "xxx",
"location": "xxx"
}
}
]
【问题讨论】:
-
序列化问题应该在那里解决。 EF Core 无济于事,因为这不是他们关心的问题(EF Core 可以毫无问题地处理循环引用)。见Related data and serialization
-
@IvanStoev 这很有帮助。我在
User类中尝试了ICollection<Items>上方的[JsonIgnore](system.text.json) 属性,它完成了与我编写的DTO 代码相同的工作!如果它在某种引用循环中,我担心其他问题,例如内存中的无限数量的对象? -
假设您有 1 个
User和 5 个Items。这 5 个Items 中的每一个的User属性都指向相同 1 个User实例。所以最后你只有 6 个对象,即根本没有额外数量的对象。 -
啊,好吧,现在更有意义了。我尝试尝试的一件事是首先使用
startup.cs中 Related Data and Serialization 示例中的代码和Microsoft.AspNetCore.Mvc.NewtonsoftJson,这样做是给我一个空的items数组user响应中的对象。所以[JsonIgnore]最适合我。谢谢。 -
顺便说一句,不要误会我的意思。解决循环引用问题并不能解决所有序列化问题(例如,如果启用了延迟加载)。与直接使用实体相比,使用 DTO 可以更好地控制来回发送的确切内容,尤其是对于返回数据。例如,如果一个相同的数据库上下文实例用于多个调用,则返回的实体可能包含相关数据,即使它没有被明确请求。