Я пытаюсь создать API-интерфейс ASP.NET Core, который возвращает объект, содержащий некоторые связанные, объединенные данные.
Но когда я вызываю модель Article с помощью Include (), он автоматически отображаетсяEF Core.Предполагается, но ... происходит непредвиденное отображение.
EF Core создает полностью сопоставленный объект для всех объектов, так что создается слишком много данных.
Например, модель пользователя имеет свойство Article икогда я вызываю модель Article, свойство User также содержит информацию об объекте Article.В результате он возвращает много дублированных данных.
В первый раз, я думаю, что это происходит из
https://docs.microsoft.com/en-us/ef/core/querying/related-data
- Стремительная загрузка
- Явная загрузка
- Ленивая загрузка
Но это не так.
Я не знаю, как настроить EF Core, чтобы не отображать всеобъекты внутри ..
* Схема и модель базы данных
введите описание изображения здесь
public class Topic
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[HiddenInput(DisplayValue = false)]
public int TopicId { get; set; }
[Required]
[StringLength(20, ErrorMessage = "Title cannot be longer than 20 characters.")]
public string Title { get; set; }
[StringLength(200, ErrorMessage = "Description cannot be longer than 200 characters.")]
public string Description { get; set; }
public byte[] Picture { get; set; }
public string PictureMimeType { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM-dd-yyyy}", ApplyFormatInEditMode = true)]
public DateTime PostDate { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM-dd-yyyy}", ApplyFormatInEditMode = true)]
public DateTime ModifyDate { get; set; }
[Display(Name = "Show")]
public bool ShowFlag { get; set; }
public int UserId { get; set; }
public virtual User User { get; set; }
public virtual ICollection<Article> Articles { get; set; }
}
public class Article
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[HiddenInput(DisplayValue = false)]
public int ArticleId { get; set; }
[Required]
[StringLength(100, ErrorMessage = "Title cannot be longer than 100 characters.")]
public string Title { get; set; }
public string Content { get; set; }
[StringLength(10, ErrorMessage = "Category cannot be longer than 10 characters.")]
public string Category { get; set; } = "Free";
public byte[] Picture { get; set; }
public string PictureMimeType { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM-dd-yyyy}", ApplyFormatInEditMode = true)]
public DateTime PostDate { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM-dd-yyyy}", ApplyFormatInEditMode = true)]
public DateTime ModifyDate { get; set; }
public int ReadCount { get; set; }
[Required]
[Display(Name = "Show")]
public bool ShowFlag { get; set; }
public int TopicId { get; set; }
public virtual Topic Topic { get; set; }
public int UserId { get; set; }
public virtual User User { get; set; }
}
public class User
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[HiddenInput(DisplayValue = false)]
public int UserId { get; set; }
[StringLength(20, ErrorMessage = "Name cannot be longer than 20 characters.")]
public string Name { get; set; }
[StringLength(255, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
public string Password { get; set; }
[DataType(DataType.EmailAddress)]
[EmailAddress]
public string Email { get; set; }
[StringLength(20, ErrorMessage = "Title cannot be longer than 20 characters.")]
public string Title { get; set; }
[StringLength(20, ErrorMessage = "Phone number cannot be longer than 20 characters.")]
[DataType(DataType.PhoneNumber)]
public string Phone { get; set; }
[StringLength(100, ErrorMessage = "Address cannot be longer than 100 characters.")]
public string Address { get; set; }
[StringLength(100, ErrorMessage = "Introduction cannot be longer than 100 characters.")]
public string Introduction { get; set; }
[DataType(DataType.Date)]
public DateTime? Birthdate { get; set; }
public byte[] Picture { get; set; }
public string PictureMimeType { get; set; }
public virtual ICollection<Topic> Topics { get; set; }
public virtual ICollection<Article> Articles { get; set; }
}
* Код контроллера
var article = await this._context.Articles
.Include(a => a.User)
.Include(a => a.Topic)
.SingleOrDefaultAsync(a => a.ArticleId == id);
* Дублированные данные
{
"articleId": 5,
"title": "Does TaskAll() really wait for all in any case?",
"content": null,
"category": "Threading",
"picture": null,
"pictureMimeType": null,
"postDate": "2018-06-18T07:00:00",
"modifyDate": "2018-06-20T07:47:42.1854485",
"readCount": 101,
"showFlag": true,
"topicId": 1,
"topic": {
"topicId": 1,
"title": "C#",
"description": "About C#",
"picture": null,
"pictureMimeType": null,
"postDate": "2018-05-28T07:00:00",
"modifyDate": "2018-05-28T23:36:04.701311",
"showFlag": true,
"userId": 1,
"user": {
"userId": 1,
"name": "",
"password": null,
"email": "",
"title": "Junior Programmer!!",
"phone": "",
"address": "",
"introduction": "Hey, I'm Jason, most motivated person to be a fullstack programmer! ",
"birthdate": null,
"picture": null,
"pictureMimeType": null,
"permissionId": 0,
"permission": null,
"topics": [],
"articles": [
{
"articleId": 5,
"title": "Does TaskAll() really wait for all in any case?",
"content": null,
"category": "Threading",
"picture": null,
"pictureMimeType": null,
"postDate": "2018-06-18T07:00:00",
"modifyDate": "2018-06-20T07:47:42.1854485",
"readCount": 101,
"showFlag": true,
"topicId": 1,
"userId": 1
}
]
},
"articles": [
{
"articleId": 5,
"title": "Does TaskAll() really wait for all in any case?",
"content": null,
"category": "Threading",
"picture": null,
"pictureMimeType": null,
"postDate": "2018-06-18T07:00:00",
"modifyDate": "2018-06-20T07:47:42.1854485",
"readCount": 101,
"showFlag": true,
"topicId": 1,
"userId": 1,
"user": {
"userId": 1,
"name": "",
"password": null,
"email": "",
"title": "Junior Programmer!!",
"phone": "",
"address": "",
"introduction": "Hey, I'm Jason, most motivated person to be a fullstack programmer! ",
"birthdate": null,
"picture": null,
"pictureMimeType": null,
"topics": [],
"articles": []
}
}
]
},
"userId": 1,
"user": {
"userId": 1,
"name": "",
"password": null,
"email": "",
"title": "Junior Programmer!!",
"phone": "",
"address": "",
"introduction": "Hey, I'm Jason, most motivated person to be a fullstack programmer! ",
"birthdate": null,
"picture": null,
"pictureMimeType": null,
"topics": [
{
"topicId": 1,
"title": "C#",
"description": "About C#",
"picture": null,
"pictureMimeType": null,
"postDate": "2018-05-28T07:00:00",
"modifyDate": "2018-05-28T23:36:04.701311",
"showFlag": true,
"userId": 1,
"articles": [
{
"articleId": 5,
"title": "Does TaskAll() really wait for all in any case?",
"content": null,
"category": "Threading",
"picture": null,
"pictureMimeType": null,
"postDate": "2018-06-18T07:00:00",
"modifyDate": "2018-06-20T07:47:42.1854485",
"readCount": 101,
"showFlag": true,
"topicId": 1,
"userId": 1
}
]
}
],
"articles": [
{
"articleId": 5,
"title": "Does TaskAll() really wait for all in any case?",
"content": null,
"category": "Threading",
"picture": null,
"pictureMimeType": null,
"postDate": "2018-06-18T07:00:00",
"modifyDate": "2018-06-20T07:47:42.1854485",
"readCount": 101,
"showFlag": true,
"topicId": 1,
"topic": {
"topicId": 1,
"title": "C#",
"description": "About C#",
"picture": null,
"pictureMimeType": null,
"postDate": "2018-05-28T07:00:00",
"modifyDate": "2018-05-28T23:36:04.701311",
"showFlag": true,
"userId": 1,
"articles": []
},
"userId": 1
}
]
}
}