Ядро базы данных Entity Framework.Include()

У вас была игра с ef core и возникла проблема с оператором include. Для этого кода я получаю 2 компании, которых я ожидал.

public IEnumerable<Company> GetAllCompanies(HsDbContext db)
{
    var c = db.Company;
    return c;
}

Это возвращает

[{"id":1,"companyName":"new","admins":null,"employees":null,"courses":null},
 {"id":2,"companyName":"Test Company","admins":null,"employees":null,"courses":null}]

Как вы можете видеть, есть 2 компании, и все связанные с ними свойства являются нулевыми, поскольку я havnt использовал какие-либо включения, что я и ожидал. Теперь, когда я обновляю метод до этого:

public IEnumerable<Company> GetAllCompanies(HsDbContext db)
{
    var c = db.Company
        .Include(t => t.Employees)
        .Include(t => t.Admins)
        .ToList();

    return c;
}

это то, что он возвращает:

[{"id":1,"companyName":"new",
  "admins":[{"id":2,"forename":"User","surname":"1","companyId":1}]
}]

Он возвращает только одну компанию и включает только администраторов. Почему в него не вошли 2 компании и их сотрудники?

public class Company
{
    public int Id { get; set; }
    public string CompanyName { get; set; }
    public List<Admin> Admins { get; set; }
    public List<Employee> Employees { get; set; }
    public List<Course> Courses { get; set; }

    public string GetFullName()
    {
        return CompanyName;
    }
}

public class Employee
{
    public int Id { get; set; }
    public string Forename { get; set; }
    public string Surname { get; set; }
    public int CompanyId { get; set; }
    [ForeignKey("CompanyId")]
    public Company company { get; set; }

    public ICollection<EmployeeCourse> Employeecourses { get; set; }
}


public class Admin
{
    public int Id { get; set; }
    public string Forename { get; set; }
    public string Surname { get; set; }
    public int CompanyId { get; set; }
    [ForeignKey("CompanyId")]
    public Company Company { get; set; }
}

Ответ 1

Я не уверен, что вы видели принятый ответ на этот question, но проблема связана с тем, как JSON Serializer имеет дело с круговыми Рекомендации. Полную информацию и ссылки на дополнительные ссылки можно найти по приведенной выше ссылке, и я бы предложил ее копать, но, короче говоря, добавление следующего в startup.cs будет настраивать сериализатор для игнорирования циклических ссылок:

services.AddMvc()
    .AddJsonOptions(options => {
        options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
    });

Ответ 2

Я тестирую ваш код, эта проблема существует в моем тесте. в этом сообщении LINK Предлагается использовать проекцию данных. для вашей проблемы Что-то вроде следующего, это работа.

[HttpGet]
public dynamic Get()
{
    var dbContext = new ApplicationContext();

    var result = dbContext.Companies
        .Select(e => new { e.CompanyName, e.Id, e.Employees, e.Admins })
        .ToList();

    return result;
}

Ответ 3

В EF Core по-прежнему не работает ленивая загрузка. См. здесь.

В качестве альтернативы вы можете использовать активную загрузку.

Прочтите эту статью

Ниже приведен метод расширения, который я создал для достижения желаемой загрузки.

Метод расширения:

public static IQueryable<TEntity> IncludeMultiple<TEntity, TProperty>(
            this IQueryable<TEntity> source,
            List<Expression<Func<TEntity, TProperty>>> navigationPropertyPath) where TEntity : class
        {
            foreach (var navExpression in navigationPropertyPath)
            {
                source= source.Include(navExpression);
            }
            return source.AsQueryable();
        }

Вызов репозитория:

public async Task<TEntity> FindOne(ISpecification<TEntity> spec)
        {
            return await Task.Run(() => Context.Set<TEntity>().AsQueryable().IncludeMultiple(spec.IncludeExpression()).Where(spec.IsSatisfiedBy).FirstOrDefault());
        }

Использование:

List<object> nestedObjects = new List<object> {new Rules()};

            ISpecification<Blog> blogSpec = new BlogSpec(blogId, nestedObjects); 

            var challenge = await this._blogRepository.FindOne(blogSpec);

Зависимости:

public class BlogSpec : SpecificationBase<Blog>
    {
        readonly int _blogId;
        private readonly List<object> _nestedObjects;

        public ChallengeSpec(int blogid, List<object> nestedObjects)
        {
            this._blogId = blogid;
            _nestedObjects = nestedObjects;
        }

        public override Expression<Func<Challenge, bool>> SpecExpression
        {
            get { return blogSpec => blogSpec.Id == this._blogId; }
        }

        public override List<Expression<Func<Blog, object>>> IncludeExpression()
        {
            List<Expression<Func<Blog, object>>> tobeIncluded = new List<Expression<Func<Blog, object>>>();
            if (_nestedObjects != null)
                foreach (var nestedObject in _nestedObjects)
                {
                    if (nestedObject is Rules)
                    {
                        Expression<Func<Blog, object>> expr = blog => blog.Rules;
                        tobeIncluded.Add(expr);
                    }

                }

            return tobeIncluded;
        }

Будет рад, если это поможет. Обратите внимание, что это не готовый код производства.