【问题标题】:How to eager load child entities using repository pattern如何使用存储库模式预先加载子实体
【发布时间】:2011-07-16 23:11:59
【问题描述】:

我有一个名为 Tour 的实体,它可以有多个 Agents。我可以添加代理,但无法删除它们。

// _repo is injected....
var tour = _repo.GetById(tourId);
tour.AddAgent(new Agent(tour.TourId));

当我尝试调用Tour.RemoveAgent() 方法时,实际上并没有删除任何内容。我在Tour.RemoveAgent() 方法中设置了一个断点,我看到_agents 属性的计数为0。

tour.RemoveAgent(agentId); // This doesn't work because _agents is empty

当我从我的存储库中检索 Tour 时,我是否必须为 EF 做一些特殊的事情来填充 _agents 属性?

更新:问题已解决(感谢 Paul 的回答)

我决定只为每个聚合创建一个唯一的存储库,这样可以很容易地使用Include() 函数准确定义需要包含的内容。这是我从 GenericRepository<T> 类继承的示例(也包含在此问题的底部)。

public class TourRepository : GenericRepository<Tour>
{
    public TourRepository(IDatabaseFactory databaseFactory) : base (databaseFactory)
    {
    }

    public override Tour GetById(Guid id)
    {
        return dataContext.Tours
                .Include(x => x.Agents)
                .Single(x => x.TourId == id);
    }
}

旅游班

public partial class Tour
{
  public Guid TourId { get; private set; }
  protected virtual List<Agent> _agents { get; set; }

  public Tour()
  {
    TourId = Guid.NewGuid();
    _agents = new List<Agent>();
  }

  public void AddAgent(Agent agent)
  {
    _agents.Add(agent);
  }

  public void RemoveAgent(Guid agentId)
  {
    _agents.RemoveAll(a => a.AgentId == agentId);
  }
}

代理类

public partial class Agent
{
  public Guid AgentId { get; private set; }
  public Guid TourId { get; private set; }
  public Tour Tour { get; private set; }

  public Agent(Guid tourId)
  {
    TourId = tourId;
    AgentId = Guid.NewGuid();
  }
}

OnModelCreating

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
  // AGENTS ============================
  modelBuilder.Entity<Agent>()
              .HasKey(x => x.AgentId)
              .Property(p => p.AgentId);

  modelBuilder.Entity<Agent>()
              .HasRequired(p => p.Tour)
              .WithMany(t => t.Agents);

  // TOURS =============================
  modelBuilder.Entity<Tour>()
              .HasKey(x => x.TourId)
              .Property(x => x.TourId);
}

存储库类

public class GenericRepository<T> : IRepository<T> where T : class {
  private MyContext dataContext;
  private readonly IDbSet<T> dbset;  
  
  public GenericRepository(IDatabaseFactory databaseFactory)
  {
    DatabaseFactory = databaseFactory;
    dbset = DataContext.Set<T>();
  }

  protected IDatabaseFactory DatabaseFactory
  {
    get;
    private set;
  }

  protected MyContext DataContext
  {
    get { return dataContext ?? (dataContext = DatabaseFactory.Get()); }
  }
  
  // ... stuff removed for brevity ...
  
  public T GetById(Guid id)
  {
    return dbset.Find(id);
  }
}

【问题讨论】:

  • 你也在使用 UoW 吗?您是否尝试过使用 Eager Loading 进行测试?
  • 你不会使用 .Find 方法,你会使用 _databaseContext.Tours.Include(x => x.Agent).Single(x => x.TourId == tourId) 你可以在这里阅读更多:blogs.msdn.com/b/adonet/archive/2011/01/31/…

标签: entity-framework-4 poco entity-framework-ctp5 ef-code-first


【解决方案1】:

尝试制作受保护的虚拟列表 _agents { get;放; } 公开

public virtual List<Agent> _agents { get; set; }

您也可以通过执行以下操作来进行预加载:

_databaseContext.Tours.Include(x => x.Agents).Single(x => x.TourId == tourId) 

您可以在这里阅读更多内容:http://blogs.msdn.com/b/adonet/archive/2011/01/31/using-dbcontext-in-ef-feature-ctp5-part-6-loading-related-entities.aspx

【讨论】:

  • 感谢您的回答。我使用您的建议对问题的解决方案更新了我的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多