net mvc framework first example español code asp asp.net-mvc entity-framework entity-framework-4 linq-to-entities entity-framework-5

asp.net mvc - mvc - en Entity framework quiero incluir solo los objetos de los primeros hijos y no los hijos de los niños(sub de sub)



mvc 5 entity framework relationships (4)

Tengo estas dos clases:

public class BusinessesTBL { public string ID { get; set; } public string FirstName { get; set; } public string lastName { get; set; } public ICollection<OffersTBL> OffersTBLs { get; set; } } public class OffersTBL { public int ID { get; set; } public string Name { get; set; } public int CatId { get; set; } public string BusinessesTBLID { get; set; } public virtual BusinessesTBL BusinessesTBLs { get; set; } }

cuando trato de traer todas las ofertas de acuerdo con el campo CatId, también debo devolver los BusinessesTBL, pero el método también devuelve las ofertas de nuevo por cada BusinessesTBL obj, Mi código es:

public IQueryable<OffersTBL> GetOffersTBLsCat(int id) { db.OffersTBLs.Include(s => s.BusinessesTBLs); }

Puede ver el resultado incorrecto en: http://priooffer.azurewebsites.net/api/OffersApi/GetOffersTBLsCat/4

Como puede ver, devuelve todas las ofertas de cada objeto de negocio mientras que el objeto de negocio de cada oferta, y solo deseo devolver las ofertas con su objeto de negocio sin oferta bajo obj.

¿Alguien podría ayudar por favor?


Debido a que OffersTBL tiene una asociación con BusinessesTBL y BusinessesTBL con OffersTBL, puede realizar un bucle infinito de entidades como OffersTBL.BusinessesTBL.OffersTBL.BusinessesTBL y así sucesivamente.

Para controlar la profundidad anidada de las Entidades, por lo general uso clases de ayuda con las propiedades necesarias en ellas.

Para NegociosTBL

public class BusinessesTBLHelper { private BusinessesTBLHelper(BusinessesTBL o){ ID = o.ID; FirstName = o.FirstName; lastName = o.LastName; OffersTBLids = new List<int>(); foreach(OffersTBL offersTbl in o.OffersTBLs){ OffersTBLids.Add(offersTbl.ID); } } public string ID { get; set; } public string FirstName { get; set; } public string lastName { get; set; } public IEnumerable<int> OffersTBLids { get; set; } //no references anymore }

Y lo mismo para su entidad OffersTBL.

public class OffersTBLHelper { private OffersTBLHelper(OffersTBL o){ ID = o.ID; Name = o.Name; CatId = o.CatId; BusinessesTBLID = o.BusinessesTBLID; BusinessesTBLs = new BusinessesTBLHelper(o.BusinessesTBLs); } public string ID { get; set; } public string Name{ get; set; } public intCatId{ get; set; } public string BusinessesTBLID { get; set; } public BusinessesTBLHelper BusinessesTBLs { get; set; } }

En la base de datos quering puede crear directamente los nuevos objetos de ayuda a partir de queryresult:

public IEnumerable<OffersTBLHelper> GetOffersTBLsCat(int id) { return db.OffersTBLs.where(s => s.CatId == id).Select(x=> new OffersTBLHelper(x)).ToList(); }

Ahora tienes todas las OfertasTBL con BusinessesTBLs bajo. El bucle se detiene aquí porque los BusinessesTBL no tienen ningún DealsTBL debajo de él. Sin embargo, solo tiene las identificaciones en una lista para futuras referencias e identificación.


Esto sucede porque Entity Framework realiza la reparación de la relación , que es el proceso que rellena automáticamente las propiedades de navegación cuando los objetos que pertenecen allí están presentes en el contexto. Por lo tanto, con referencias circulares, puede profundizar las propiedades de navegación sin cesar incluso cuando la carga perezosa está deshabilitada. El serializador Json hace exactamente eso (pero aparentemente está instruido para tratar con referencias circulares, por lo que no está atrapado en un bucle sin fin).

El truco es evitar que la reparación de la relación se vuelva a pasar La ChangeTracker relación se basa en el ChangeTracker del contexto, que almacena en caché los objetos para rastrear sus cambios y asociaciones. Pero si no hay nada que rastrear, no hay nada que arreglar. Puede detener el seguimiento llamando a AsNoTracking() :

db.OffersTBLs.Include(s => s.BusinessesTBLs) .AsNoTracking()

Si además de eso, también inhabilitas la carga contextConfiguration.LazyLoadingEnabled = false en el contexto (al establecer contextConfiguration.LazyLoadingEnabled = false ), verás que solo OffersTBL.BusinessesTBLs se completan en la cadena Json y que BusinessesTBL.OffersTBLs está vacío.

Una ventaja adicional es que AsNoTracking() aumenta el rendimiento, ya que el rastreador de cambios no está ocupado en el seguimiento de todos los objetos que EF materializa. De hecho, siempre debe usarlo en una configuración desconectada.


Ha desactivado la carga diferida en las OfferTBL que la hacen no virtual. ¿Qué pasa si activa la carga perezosa? Me gusta esto:

public class BusinessesTBL { public string ID { get; set; } public string FirstName { get; set; } public string lastName { get; set; } //put a virtual here public virtual ICollection<OffersTBL> OffersTBLs { get; set; } }

Entonces, asegúrese de no llamar / incluir a OfferTBLs al serializar. Si los OfferTBLs siguen regresando, es porque los está buscando en algún lugar de su código. Si esto sucede, edite su pregunta y pegue todo el código, incluida la lógica de serialización.


Suponiendo que el objeto no es nulo y simplemente está vacío:

public IQueryable<OffersTBL> GetOffersTBLsCat(int id) { db.OffersTBLs.Include(s => s.BusinessesTBLs).Where(x => !x.BusinessesTBLs.OffersTBLs.Any()); }

Editar: Filtrar antes de incluir:

public IQueryable<OffersTBL> GetOffersTBLsCat(int id) { db.OffersTBLs.Where(x => !x.BusinessesTBLs.OffersTBLs.Any()) .Include(s => s.BusinessesTBLs); }