实体框架加入解释

Moh*_*adr 5 c# linq entity-framework join

我有以下实体

//Active Auction Entity
public class ActiveAuction
{
    public int Id { get; set; }

    public string Title { get; set; }

    public int? FirstAuctionId { get; set; }

    public int? SecondAuctionId { get; set; }

    public int? ThirdAuctionId { get; set; }

    public virtual Auction FirstAuction { get; set; }

    public virtual Auction SecondAuction { get; set; }

    public virtual Auction ThirdAuction { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
// Auction Entity
public class Auction
{
    public int AuctionId { get; set; }

    public AuctionStatus AuctionStatus { get; set; }

    public int? DepartmentId { get; set; }

    public virtual Department Department { get; set; }

}
Run Code Online (Sandbox Code Playgroud)
// Department Entity
public class Department
{
    public int DepartmentId { get; set; }

    public string DepartmentName { get; set; }

    public int? AdminId { get; set; }

    public virtual Admin Admin { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我正在试图做的是让Active AuctionsAuctions加载和AuctionDepartments装我知道我应该写Include为被加载的每一个对象,以便由EF生成的SQL将连接语句选择对象有我

但这是现有的代码

 using (var dc = DataContext())
    {
        await dc.Auction
           .Include("Department.Admin")
           .Where(i => i.Id == id && i.AuctionStatus == AuctionStatus.Accepted).ToListAsync();

        return await dc.ActiveAuction.
           SingleOrDefaultAsync(i => i.Id == id);
    }
Run Code Online (Sandbox Code Playgroud)

我不知道如何,但此代码工作,并返回ActiveAuctions包括所有所需的对象

我检查了针对数据库执行的SQL,并按预期生成单独的查询.

我想要一个解释,了解返回如何ActiveAcutions加载与其他提到的实体!!?

Evk*_*Evk 5

原因很简单.您很可能知道,Entity Framework会跟踪您从数据库中获取的实体,主要是检测对它们的更改,并在您调用时将这些更改应用于数据库SaveChanges.但是,这意味着到目前为止,EF上下文具有从数据库中提取的实体缓存.

编辑:正如@GertArnold在评论中正确指出的那样 - 我对动态代理的解释是完全错误的 - 即使ProxyCreationEnabled是这样也是这样false.真正的原因是关系修复,它在DetectChanges被调用时由实体框架执行(它在各种事件上隐式调用,例如将实体附加到上下文,或执行查询DbSet).在该关系修复期间,EF同步导航属性和外键,在您的情况下会导致您观察到的行为.有关MSDN中关系修复的更多信息

要验证这一点,您可以使用以下简单代码:

using (var ctx = new TestEntities()) {
     ctx.Configuration.LazyLoadingEnabled = false;                
     ctx.Configuration.ProxyCreationEnabled = false;                
     var code = ctx.Codes.First();                
     var error = ctx.Errors.First();
     Debug.Assert(Object.ReferenceEquals(error.Code, code));                                
}
Run Code Online (Sandbox Code Playgroud)

这里我首先获取一些实体(Code),然后我获取另一个具有导航属性Code的实体(Error).您看到延迟加载被禁用.以下断言将通过,因为error.Code和代码是相同的.NET对象,它确认它是从上下文缓存中获取的.