簡體   English   中英

EF Eager加載包括多個

[英]EF Eager loading include multiple

我有這個存儲庫:

public class Repository<T> : IRepository<T> where T : class
{
    private readonly DbContext context;
    private readonly DbSet<T> dbEntitySet;

    public Repository(DbContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");

        this.context = context;
        this.dbEntitySet = context.Set<T>();
    }

    public IEnumerable<T> GetAll()
    {
        return this.dbEntitySet;
    }

    public IEnumerable<T> GetAll(string include)
    {
        return this.dbEntitySet.Include(include);
    }

    public IEnumerable<T> GetAll(string[] includes)
    {
        IQueryable<T> query = context.Set<T>();
        foreach (var include in includes)
            query.Include(include);

        return query;
    }

    public void Create(T model)
    {
        this.dbEntitySet.Add(model);
    }

    public void Update(T model)
    {
        this.context.Entry<T>(model).State = EntityState.Modified;
    }

    public void Remove(T model)
    {
        this.context.Entry<T>(model).State = EntityState.Deleted;
    }

    public void Dispose()
    {
        this.context.Dispose();
    }
}

我有一個服務,看起來像這樣:

public class Service<T> where T : class
{
    private readonly IRepository<T> repository;

    protected IRepository<T> Repository
    {
        get { return this.repository; }
    }

    internal Service(IUnitOfWork unitOfWork)
    {
        this.repository = unitOfWork.GetRepository<T>();
    }
}

我的頁面服務看起來像這樣(簡化):

public class PageService : Service<Page>
{

    // ...

    public IList<Page> GetPublished()
    {
        return this.Repository.GetAll(new string[] { "ForbiddenUsers", "ForbiddenGroups" }).Where(model => model.Published).ToList();
    }

    // ...

}

為了清楚起見,我的頁面看起來像這樣:

public enum PageType
{
    Root,
    System,
    Page,
    Link,
    Group
}

public partial class Page
{
    public int Id { get; set; }
    public System.DateTime DateCreated { get; set; }
    public string CreatedById { get; set; }
    public Nullable<System.DateTime> DateModified { get; set; }
    public string ModifiedById { get; set; }
    public string CompanyId { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public string FileName { get; set; }

    public string Path { get; set; }
    public string ViewData { get; set; }
    public string ViewTitle { get; set; }

    public string Link { get; set; }
    public bool Published { get; set; }
    public PageType Type { get; set; }
    public int Order { get; set; }
    public string Lineage { get; set; }
    public Nullable<int> ParentId { get; set; }
    public bool Restricted { get; set; }
    public bool Deleted { get; set; }

    public Company Company { get; set; }
    public User CreatedBy { get; set; }
    public User ModifiedBy { get; set; }
    public Page Parent { get; set; }
    public MenuPage MenuPage { get; set; }
    public ICollection<Page> Pages { get; set; }
    public ICollection<User> ForbiddenUsers { get; set; }
    public ICollection<Group> ForbiddenGroups { get; set; }
}

當我運行此代碼時, ForbiddenUsersForbiddenGroups始終為null。 如果我檢查調用堆棧,我可以看到生成的查詢如下所示:

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[DateCreated] AS [DateCreated], 
[Extent1].[CreatedById] AS [CreatedById], 
[Extent1].[DateModified] AS [DateModified], 
[Extent1].[ModifiedById] AS [ModifiedById], 
[Extent1].[CompanyId] AS [CompanyId], 
[Extent1].[Name] AS [Name], 
[Extent1].[Description] AS [Description], 
[Extent1].[FileName] AS [FileName], 
[Extent1].[Path] AS [Path], 
[Extent1].[ViewData] AS [ViewData], 
[Extent1].[ViewTitle] AS [ViewTitle], 
[Extent1].[Link] AS [Link], 
[Extent1].[Published] AS [Published], 
[Extent1].[Type] AS [Type], 
[Extent1].[Order] AS [Order], 
[Extent1].[Lineage] AS [Lineage], 
[Extent1].[ParentId] AS [ParentId], 
[Extent1].[Restricted] AS [Restricted], 
[Extent1].[Deleted] AS [Deleted]
FROM [dbo].[Pages] AS [Extent1]

如你所見,這完全忽略了我的包含。

如果我將服務方法更改為:

public IList<Page> GetPublished()
{
    return this.Repository.GetAll("ForbiddenUsers").Where(model => model.Published).ToList();
}

現在運行我的代碼, ForbiddenUsers現在已填充,調用堆棧顯示正確生成的查詢(太大而無法在此處粘貼)。

我需要允許多個包含但我無法弄清楚他們為什么不工作....

任何幫助將不勝感激....

您應該將包含的查詢分配回查詢變量,因為QueryableExtensions.Include創建新的DbQuery<T>而不是修改現有的DbQuery<T> 另外我建議你使用params來包含路徑:

public IEnumerable<T> GetAll(params string[] includes)
{
    IQueryable<T> query = context.Set<T>();
    foreach (var include in includes)
        query = query.Include(include);

    return query;
}

這將允許您傳遞所有包含的路徑,而無需顯式創建數組:

public IList<Page> GetPublished()
{
    return Repository.GetAll("ForbiddenUsers", "ForbiddenGroups")
                     .Where(model => model.Published)
                     .ToList();
}

嘗試

   foreach (var include in includes)
        query = query.Include(include);

    return query;

下面是C#6中的一個例子。 此外,請注意使用nameof運算符使代碼更易於維護,以便在重命名時不需要手動更新屬性名稱的字符串值。

// Assign the property names
var navigablePropertyNames = new[]
{
    nameof(ParentEntity.Id),
    nameof(ParentEntity.Name),
    nameof(ParentEntity.Description)
};

// Do the inclusion
GetAll(navigablePropertyNames);

所以針對您的具體要求:

public IEnumerable<T> GetAll(params string[] inclusions)
{
    var qry = this.dbEntitySet.AsQueryable();

    foreach(var inclusion in inclusions)
    {
        qry  = qry.Include(inclusion);
    }

    return qry;
}

用途:

// either 
var resultSet1 = GetAll(nameof(ParentEntity.Id),
    nameof(ParentEntity.Name),
    nameof(ParentEntity.Description));

// or
var propertyNames = new[] {
    nameof(ParentEntity.Id),
    nameof(ParentEntity.Name),
    nameof(ParentEntity.Description)};

var resultSet2 = GetAll(propertyNames);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM