#c# #ef-code-first #entity-framework-4 #lazy-loading #asp.net-apicontroller
#c# #ef-code-first #entity-framework-4 #отложенная загрузка #asp.net-apicontroller
Вопрос:
Я пытаюсь правильно спроектировать структуру метода контроллера Api со следующим объектом в качестве возвращаемого типа:
var obj= new CustomObject
{
Id = a.Id,
stampleProperty= a.stampleProperty,
stampleProperty= a.stampleProperty2,
B= a.B,
};
Базовый сценарий состоит из двух объектов A и B, которые имеют отношение «Многие ко многим», как описано ниже:
public class A
{
public int AId { get; set; }
public string sampleProperty{ get; set; }
public string sampleProperty2{ get; set; }
public virtual ICollection B { get; set; }
}
public class B
{
public int BId { get; set; }
public string sampleProperty3{ get; set; }
public string sampleProperty4{ get; set; }
public int ComyId { get; set; }
public virtual ICollection A{ get; set; }
public virtual Comy Comy{ get; set; }
}
Примечание: я не могу изменить структуру базы данных. Кроме того, я ищу наилучший возможный способ извлечения реляционных объектов B из объекта A, без виртуальных свойств B из A.
Код, который я опробовал на контроллере, хотя он использует подход «ленивой загрузки», возвращает встроенные объекты типа A внутри каждого связанного объекта типа B.
var a = db.A.FirstOrDefault(a => a.stampleProperty== stampleProperty);
var obj= new CustomObject
{
Id = a.AId,
sampleProperty= a.sampleProperty,
sampleProp= a.sampleProp,
B = a.B,
};
Возврат:
{
"AId":
"sampleProperty":
"sampleProp":
"B":[{
"BId":
"sampleProperty3":
"sampleProperty4":
"ComyId":
"A":[ **REFERENCE LOOP** ]
"ComyId":
"Comy":{}
}]
}
Цель: объекты B без виртуальных свойств A.
В связи с тем, что я нахожусь в процессе изучения этого фреймворка, я ищу правильный подход к использованию этих инструментов, избегая необработанных SQL-запросов и множественных запросов.
Ответ №1:
Я бы предложил создать дополнительный пользовательский объект и сопоставить поля (либо вручную, либо с помощью фреймворка, подобного AutoMapper).
Применительно к вашему примеру это может выглядеть примерно так:
public class CustomObjectA
{
public int Id { get; set; }
public string stampleProperty { get; set; }
public string stampleProperty2 { get; set; }
public CusomObjectB[] B { get; set; }
}
public class CustomObjectB
{
public int BId { get; set; }
public string sampleProperty3{ get; set; }
public string sampleProperty4{ get; set; }
public int ComyId { get; set; }
}
И использование будет выглядеть следующим образом:
var a = db.A.FirstOrDefault(a => a.stampleProperty== stampleProperty);
var obj= new CustomObjectA
{
Id = a.AId,
sampleProperty= a.sampleProperty,
sampleProp= a.sampleProp,
B = a.B.Select(b => new CustomObjectB
{
BId = b.BId,
sampleProperty3 = b.sampleProperty3
//etc...
}).ToArray()
};
Не обязательно возвращать объекты базы данных прямо из API по такого рода причинам (наряду с некоторыми другими, например, вы можете не хотеть, чтобы третьи стороны, использующие ваш API, могли видеть каждое свойство в базе данных).
Общим термином для этого подхода является использование DTO (объекты передачи данных). Вот руководство от Microsoft, где они обсуждают это подробнее https://learn.microsoft.com/en-us/aspnet/web-api/overview/data/using-web-api-with-entity-framework/part-5 .
Комментарии:
1. Примечание: опечатки оставлены намеренно, чтобы соответствовать примерам кода вопроса.