實體框架核心.Include()問題

c# entity-framework-core

一直在玩ef核心,並且在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家公司,所有相關的屬性都是null,因為我曾經使用過任何包含,這正是我的預期。現在,當我將方法更新為:

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
            }
        ]
    }
]

它只返回一家公司,只包括管理員。為什麼不包括這兩家公司及其員工?

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; }
}

一般承認的答案

我不確定你是否已經看到了這個問題的公認答案,但問題在於JSON Serializer如何處理循環引用。有關更多參考資料的完整詳細信息和鏈接可以在上面的鏈接中找到,我建議深入研究這些內容,但簡而言之,將以下內容添加到startup.cs將配置序列化程序以忽略循環引用:

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

熱門答案

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;
        }

如果它有幫助會很高興。請注意,這不是生產就緒代碼。



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow