环境:
.NET 6
我想做的是在实体之间建立一对多的关系。
我想我对实体导航属性的建模是错误的。我收到循环引用错误。
我使用
.NET 6
和 Entity Framework 代码优先方法来建模我的数据库。我的大多数关系都是一对多。
当我尝试使用 Postman 发出请求时,我得到的响应是一条错误消息,告诉我它是循环引用。我的对象相互引用。
如果有人能解决这个问题并向我解释我做错了什么:)
在“一”侧,有一个导航属性。此外,它还包含一个外键属性,例如
entityId
,它与另一个实体建立关系。
在“多”方面,有一个包含多个实例的集合的导航属性。
以下是我如何构建实体及其配置的一些示例代码:
public class Author
{
public Guid Id { get; set; }
public string Name { get; set; }
public ICollection<Book> Books { get; set; }
}
public class Book
{
public Guid Id { get; set; }
public Guid AuthorId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public Author author { get; set; }
public ICollection<Genre> Genres{ get; set; }
}
public class Genre
{
public Book Book {get;set;}
public Guid BookId {get;set;}
public string Name { get; set; }
}
public class BookEntityTypeConfiguration : IEntityTypeConfiguration<Book>
{
public void Configure(EntityTypeBuilder<Book> builder)
{
builder.HasOne(b => b.author)
.WithMany(a => a.Books)
.HasForeignKey(b => b.AuthorId);
}
}
public class GenreEntityTypeConfiguration : IEntityTypeConfiguration<Genre>
{
public void Configure(EntityTypeBuilder<Genre> builder)
{
builder.HasOne(g => g.Book)
.WithMany(b => b.Genres)
.HasForeignKey(g => g.BookId);
}
}
创建
Data Transfer Objects
或 DTOs
。您可以控制序列化并且没有循环引用。
示例代码:
public class AuthorDto
{
public Guid Id { get; set; }
public string Name { get; set; }
// Exclude the Books collection or selectively choose what to include
}
public class BookDto
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
// References AuthorId only, or include an AuthorDto with limited data
public Guid AuthorId { get; set; }
// Similar for Genres, decide on the level of detail you want
}
要忽略周期,您可以在
Startup.cs
中进行配置。
For System.Text.Json:
builder.Services.AddControllersWithViews()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.IgnoreCycles;
options.JsonSerializerOptions.WriteIndented = true;
});
For Newtonsoft.Json:
builder.Services.AddControllersWithViews()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
开发人员经常使用
DTOs
,而不是直接将数据库模型连接到 API
。这有助于避免循环引用等问题,并增强安全性和可维护性。使用DTOs
分离内部数据结构,使数据传输更加顺畅。在 .NET
和 Entity Framework
中,配置序列化器来处理复杂的对象图是明智的。