#c# #json #entity-framework #asp.net-web-api #serialization
#c# #json #entity-framework #asp.net-web-api #сериализация
Вопрос:
У меня есть веб-API с ASP.NET и я пытаюсь вернуть некоторые данные, но это вызывает проблемы, поскольку они ссылаются на объекты, на которые я не хочу ссылаться.
Структура класса в этом случае следующая:
Entitats (сущности), Equips (команды) и Esports (спорт)
У объекта много команд, а у одной команды есть только один вид спорта.
Я использую Entity Framework, и объекты имеют отношения в обоих направлениях; в спорте много команд, а у команды есть сущность.
Вот запрос, который я делаю, чтобы получить объект с его командой, и каждая команда со своим видом спорта.
entitats _entitat = (
from e in db.entitats
.Include("equips.esports")
where e.id == id
select e
).FirstOrDefault();
Это должно дать мне именно то, что я хочу, проблема в том, что в первой команде, когда она показывает мне спорт, спорт содержит все другие команды (из этого объекта), которые имеют тот же вид спорта, а затем, когда пришло время показать их в массиве Team, он использует $ ref и $ id.
"$id": "1",
"equips": [
{
"$id": "2",
"activitats_concedides": [],
"activitats_demanades": [],
"categories": null,
"categories_competicio": null,
"competicions": null,
"entitats": {
"$ref": "1"
},
"esports": {
"$id": "3",
// These shouldn't even be here
"equips": [
{
"$ref": "2"
},
{
"$id": "4",
"activitats_concedides": [],
"activitats_demanades": [],
"categories": null,
"categories_competicio": null,
"competicions": null,
"entitats": {
"$ref": "1"
},
"esports": {
"$ref": "3"
},
"sexes": null,
"id": 8,
"nom": "Test 2",
"id_entitat": 1,
"id_categoria": 3,
"id_esport": 1,
"id_competicio": 2,
"id_categoria_competicio": null,
"id_sexe": 3,
"borrat": false
},
{
"$id": "5",
"activitats_concedides": [],
"activitats_demanades": [],
"categories": null,
"categories_competicio": null,
"competicions": null,
"entitats": {
"$ref": "1"
},
"esports": {
"$ref": "3"
},
"sexes": null,
"id": 9,
"nom": "Test 3",
"id_entitat": 1,
"id_categoria": 2,
"id_esport": 1,
"id_competicio": 2,
"id_categoria_competicio": null,
"id_sexe": 2,
"borrat": false
},
{
"$id": "6",
"activitats_concedides": [],
"activitats_demanades": [],
"categories": null,
"categories_competicio": null,
"competicions": null,
"entitats": {
"$ref": "1"
},
"esports": {
"$ref": "3"
},
"sexes": null,
"id": 10,
"nom": "prova",
"id_entitat": 1,
"id_categoria": 3,
"id_esport": 1,
"id_competicio": 2,
"id_categoria_competicio": null,
"id_sexe": 2,
"borrat": false
}
],
"id": 1,
"nom": "Futbol"
},
"sexes": null,
"id": 3,
"nom": "Test 1",
"id_entitat": 1,
"id_categoria": 6,
"id_esport": 1,
"id_competicio": 1,
"id_categoria_competicio": null,
"id_sexe": 1,
"borrat": false
},
{
"$ref": "4" // These should be the "full" objects
},
{
"$ref": "5"
},
{
"$ref": "6"
}
],
"telefons": [],
"id": 1,
"nom": "Futbol Club Sant Cugat del Valles",
"direccio": "Sample Carrer 1",
"cif": "B12345678",
"temporada": "2019 ",
"correu": "entitat1@test.com",
"facebook": null,
"instagram": null,
"twitter": null,
"password": "8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92",
"borrat": true}
Я не спрашивал команды по каждому виду спорта, поэтому я не знаю, почему он их показывает. То же самое происходит с объектом Teams, в данном случае это не проблема, потому что это не влияет на вывод, но в других случаях это так. Я полагаю, что это означает, что если он показывает вам объекты, которые вы «спросили», как можно ближе к началу, а затем в том месте, где они вам действительно нужны, он просто ссылается.
Если вы, ребята, знаете, что не так, я был бы очень признателен. Спасибо!
PD: Я безуспешно пытался изменить этот параметр, это только ухудшает ситуацию.
var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
Комментарии:
1. Честно говоря, я думаю, вам не следует хранить команды в спортивных состязаниях, а вместо этого добавить эту функциональность в запрос. Если вы получаете sport для команды, вы также получите команды, которые относятся к спорту, потому что эти команды также хранятся в sport.. Вместо этого вы могли бы запросить команды и отфильтровать их по определенному виду спорта. Рассуждения, которые я использую для этого, следующие: команда не может существовать без спорта, но спорт может существовать без каких-либо команд. Я бы сказал, что нет необходимости хранить команды в виде спорта из-за этого, команды уже указывают вид спорта.
2. Проблема в том, что EF сгенерировал эту модель, я, конечно, могу ее изменить, но если бы я мог изменить атрибуты модели для этого конкретного контроллера, это было бы здорово. Моя главная проблема — это JSON, содержащий объекты, о которых я не просил.
3. У команд есть и другие классы, на самом деле их много, но они не отображаются, потому что я их не запрашивал. Похоже, что происходит то, что если у команды есть объект, который находится в JSON (где-нибудь еще, скажем, сущность), он показывает это, с другими объектами в команде этого не происходит.
Ответ №1:
Ваша проблема возникает из-за того, что вы слишком либерально относитесь к своим отношениям с данными. есть два способа решить эту проблему:
-
приведите в порядок свои взаимосвязи с данными. Примером может служить ваш спортивный объект, его не нужно привязывать к каким-либо командам. У вас есть команды, отлично, с каждой командой связан вид спорта, на этом все заканчивается, есть отношения один на один и ничего больше. Затем вы можете легко создать запрос, который покажет вам все команды, с которыми связан определенный вид спорта.
-
Сохраните свою структуру такой, какая она есть, но добавьте некоторые DTO для возврата из вашего API, что, честно говоря, и следует делать в первую очередь, какой бы вариант вы ни выбрали. Одна из причин, по которой вы никогда не должны возвращать объекты Entity Framework, заключается в том, что они поставляются со всеми видами данных, которые вам не нужны.
Итак, в вашем запросе, где вы выполняете свой выбор, создайте DTO, который содержит только те поля, которые вы хотите, а затем верните их, и ваша проблема будет решена.
select e
становится
select new EntityDTO {
assign whatever fields you need here
}
Таким образом, вы разрываете свою ссылку на объекты entity Framework и все их зависимости.
Может быть , немного почитайте что — нибудь вроде этого : https://entityframework.net/knowledge-base/12568587/linq-to-sql-select-into-a-new-class