9
I have a Web Api
I’m developing using the DotNet Core
and EF Cor
but is with the Lazy Loading
active, only that in some cases I need to load the entities daughters and daughters of daughters, I created a generic repository to perform CRUD
on the bench, I can carry the daughters, but the daughters of daughters can’t.
The generic Get function that carries daughters.
public IQueryable<T> Get<T>(Expression<Func<T, bool>> predicate, params string[] include)
where T : class
{
IQueryable<T> result = this._context.Set<T>().Where(predicate);
foreach (string item in include)
{
result = result.Include(item).AsQueryable();
}
return result.AsQueryable();
}
Using this function would be
var entidade this.repository.Get<Entity>(x => x.Id == 1, "Filha1", "Filha2")
.FirstOrDefault();
entidade.Filha1 // Carrega Corretamente
entidade.Filha2 // Carrega Corretamente
entidade.Filha1.SubFilha1 // Quero conseguir carregar esse nível da entidade
Implementation of the Generic Repository:
using API.Model.Context;
using API.Model.Entities;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace API.Model.Repositories
{
public class Repository : IDisposable, IRepository
{
private readonly ApiContext _context;
public Repository(ApiContext context)
{
this._context = context;
}
public void Add<T>(T obj) where T : class
{
this._context.Set<T>().Add(obj);
}
public void Delete<T>(Func<T, bool> predicate) where T : class
{
this._context.Set<T>().Where(predicate).ToList()
.ForEach(del => this._context.Set<T>().Remove(del));
}
public void Dispose()
{
this._context.Dispose();
}
public void Edit<T>(T obj) where T : class
{
this._context.Entry<T>(obj).State = EntityState.Modified;
}
public int ExecuteSql(string psSql, params object[] poParams)
{
return _context.Database.ExecuteSqlCommand(psSql, poParams);
}
public T Find<T>(params object[] key) where T : class
{
return this._context.Set<T>().Find(key);
}
public IQueryable<T> Get<T>(Expression<Func<T, bool>> predicate)
where T : class
{
return this._context.Set<T>().Where(predicate)
.AsQueryable();
}
public IQueryable<T> Get<T>(Expression<Func<T, bool>> predicate,
params string[] include)
where T : class
{
IQueryable<T> result = this._context.Set<T>().Where(predicate);
foreach (string item in include)
{
result = result.Include(item).AsQueryable();
}
return result.AsQueryable();
}
public IQueryable<T> GetAll<T>() where T : class
{
return this._context.Set<T>();
}
public void Save()
{
this._context.SaveChanges();
}
}
}
Parent Entity
[Table("Booking")]
public class Booking
{
public int Id { get; set; }
public virtual ICollection<RoomStay> RoomStay { get; set; }
}
Entity Filha
[Table("RoomStay")]
public class RoomStay
{
public int Id { get; set; }
public int BookingId { get; set; }
[ForeignKey("BookingId")]
public virtual Booking Booking { get; set; }
public int? RoomTypeId { get; set; }
[ForeignKey("RoomTypeId")]
public virtual RoomType RoomType { get; set; }
public virtual ICollection<RoomStayGuest> RoomStayGuest { get; set; }
public virtual ICollection<RoomStayFnrh> RoomStayFnrh { get; set; }
}
I need to upload Roomtype entities and Roomstayguest and Roomstayfnrh collections
This is the big problem of making a repository with the Entity Framework. Notice that you have a
.Where()
simple along with a.include()
, which has become somewhat complex due to its repository. More about: link– Gabriel Coletta
have you tried to use your logic in your loop to load the next level ? that is after you do the result = result.Include(item). Asqueryable(); and get the entity.Filha1 novate the loop to include the next level.
– Marco Souza
@Gabrielcoletta very interesting the positioning on the repositories in this link
– Lucas Riechelmann Ramos
@Lucasriechelmannramos which of the answers you used to solve your problem?
– novic
@Virgilionovic your reply, was the best for my situation, thank you
– Lucas Riechelmann Ramos
@Lucasriechelmannramos because I’m asking, because the answer with acceptance is in trouble ... that was my concern.
– novic