EF7(RC2)从实体返回所有虚拟集合的奇怪问题,而不使用Include

时间:2016-05-22 05:00:34

标签: c# entity-framework asp.net-core entity-framework-core

看起来像Entity Framework 7,虽然不支持/实现延迟加载,但是在不使用Include(...)方法的情况下返回给定实体的所有关系。

我不确定在此情况下我应遵循预期的行为。请参阅下面的复制品。请注意,this github branch/commit会重现这一点。

添加DbContext和存储库提供商:

// In ConfigureServices
services.AddDbContext<PouarfDbContext>(options => options.UseInMemoryDatabase());
services.AddScoped<IContactProvider, ContactProvider>();

种子申请数据:

// In Configure
// CreateSampleData() adds a bunch of `People` objects to a list, 
//  and then loops through them, adding each one to the DbContext 
//  through the `ContactProvider`
Task.Run(async () => 
  await new 
  MockPeople(app
      .ApplicationServices
      .GetService<IContactProvider>()).CreateSampleData());

ContactProvider实施中的几个例子:

public async Task AddPerson(Person person)
{
    await Task.Run(() => _dbContext.Add(person));
}

public async Task<IEnumerable<Person>> GetPeople()
{
    // Notice no Include(...)
    return await _dbContext.People.ToListAsync();
}

人物对象:

public class Person : ContactInformationBase // Contains Id
{
    ...

    public virtual ICollection<PhoneNumber> PhoneNumbers { get; set; }
}

然后在我的控制器操作中,我从EF获得了人员:

public async Task<IActionResult> Index()
{
    // Contains a populated list of `PhoneNumbers`, even though
    //  they should only be included if I explicitly asked EF7 to load them.
    var people = await _contactProvider.GetPeople();
    ..
}

基本上,EF7提供了来自我的主对象的映射实体,即使它们只应在我明确要求时通过Include(p => p.PhoneNumbers)包含。

我正在使用带有Entity Framework 7的ASP.NET Core 1 RC2

修改

刚刚向我的控制器添加了一个API动作,结果是......奇怪。

[Route("api/[action]")]
public async Task<IEnumerable<Person>> People()
{
    // True adds all the Includes off the DbSet as needed.
    return await _contactProvider.GetPeople(true);
}

现在我没有通过此调用返回任何映射实体。如果我删除或添加Include()来电,则不会对结果产生影响。仅返回核心Person实体,所有映射实体均为null

1 个答案:

答案 0 :(得分:1)

正如我所提到的here,问题是我自己的错。

问题在于在DbSet上使用Include模式。

我有这个,错误

var people = _dbContext.People;

if (includeRelationships)
{
    people.Include(p => p.PhoneNumbers)
        .Include(p => p.EmailAddresses)
        .Include(p => p.StreetAddresses);
}

return await people.FirstOrDefaultAsync(p => p.Id.Equals(id));

并将其更改为此,请注意此处Include的实际应用, RIGHT

IQueryable<Person> people = _dbContext.People;
if (includeRelationships)
{
    people = people
        .Include(p => p.EmailAddresses)
        .Include(p => p.PhoneNumbers)
        .Include(p => p.StreetAddresses);
}

return await people.FirstOrDefaultAsync(p => p.Id.Equals(id));