Entity Framework - 导航 属性 未 Eager/Lazy 加载?
Entity Framework - Navigation Property Not Eager/Lazy Loaded?
我有以下实体:
public class Ticket
{
public int Id { get; set; }
public string RequestBy { get; set; }
public int PriorityId { get; set; }
public ApplicationUser Requester { get; set; }
public Priority Priority { get; set; }
}
public class ApplicationUser
{
public ApplicationUser()
{
Id = Guid.NewGuid().ToString();
}
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Priority
{
public int Id { get; set; }
public string Name { get; set; }
}
当我在我的控制器中创建一个新的 Ticket 时:
public class BaseController : Controller
{
protected readonly IUnitOfWork UnitOfWork;
public BaseController(IUnitOfWork unitOfWork)
{
UnitOfWork = unitOfWork;
}
}
public class TicketController : BaseController
{
public TicketController(IUnitOfWork unitOfWork) : base(unitOfWork) { }
[HttpPost]
public ActionResult CreateTicket(CreateTicketVM viewModel)
{
// repopulate dropdowns incase we need to return view
// viewModel.Priorities is IEnumerable list
viewModel.Priorities = UnitOfWork.PriorityRepository.GetPriorities();
//validation code removed for brevity...
var ticket = new Ticket
{
RequestBy = !string.IsNullOrEmpty(viewModel.RequestBy) ? viewModel.RequestBy : User.Identity.GetUserId(),
PriorityId = viewModel.PriorityId != 0 ? viewModel.PriorityId : (int)PriorityLevel.Medium,
};
UnitOfWork.TicketRepository.Add(ticket);
}
}
现在,当我在调用 .Add(ticket)
后调试 var ticket
时,为什么它加载了相关导航 属性 Priority
而不是 Requester
导航 属性 尽管设置了 RequestBy
值?如您所见,我还没有针对任一导航属性定义任何 virtual
关键字?
Strangley 这只发生在 ApplicationUser
类型的所有导航属性中。即使不使用 virtual
关键字,所有其他导航属性似乎也会加载???
使用流利的 api 我定义了 RequestBy
FK 如下:
modelBuilder.Entity<Ticket>()
.HasRequired(x => x.Requester)
.WithMany()
.HasForeignKey(x => x.RequestBy);
下面是提供更多上下文的附加代码。
票证存储库:
public class TicketRepository : ITicketRepository
{
private readonly ApplicationDbContext _context;
public TicketRepository(ApplicationDbContext context)
{
_context = context;
}
public void Add(Ticket ticket)
{
_context.Ticket.Add(ticket);
}
}
优先存储库:
public class PriorityRepository : IPriorityRepository
{
private readonly ApplicationDbContext _context;
public PriorityRepository(ApplicationDbContext context)
{
_context = context;
}
public IEnumerable<Priority> GetPriorities()
{
return _context.Priority.ToList();
}
}
工作单元:
public class UnitOfWork : IUnitOfWork
{
private readonly ApplicationDbContext _context;
public ITicketRepository TicketRepository { get; private set; }
public IPriorityRepository PriorityRepository { get; private set; }
public UnitOfWork(ApplicationDbContext context)
{
_context = context;
TicketRepository = new TicketRepository(_context);
PriorityRepository = new PriorityRepository(_context);
}
public void Complete()
{
_context.SaveChanges();
}
}
两个导航 属性 都不应加载。您看到的很可能是所谓的导航 属性 修复功能的结果 - 如果实体已被上下文跟踪,EF 会更新引用它的实体的导航属性,即使您没有特别要求。
您可以使用 var _context = new YourDbContext();
局部变量而不是 _context
字段轻松验证这一点。或者像这样:
var ticket = new Ticket
{
RequestBy = !string.IsNullOrEmpty(viewModel.RequestBy) ? viewModel.RequestBy : User.Identity.GetUserId(),
PriorityId = viewModel.PriorityId != 0 ? viewModel.PriorityId : (int)PriorityLevel.Medium,
};
bool priorityLoaded = _context.Priority.Local.Any(e => e.Id == ticket.PriorityId);
bool userLoaded = _context.ApplicationUser.Local.Any(e => e.Id == ticket.RequestBy);
_context.Ticket.Add(ticket);
根据您的描述,priorityLoaded
应该是 true
而 userLoaded
- false
.
我有以下实体:
public class Ticket
{
public int Id { get; set; }
public string RequestBy { get; set; }
public int PriorityId { get; set; }
public ApplicationUser Requester { get; set; }
public Priority Priority { get; set; }
}
public class ApplicationUser
{
public ApplicationUser()
{
Id = Guid.NewGuid().ToString();
}
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Priority
{
public int Id { get; set; }
public string Name { get; set; }
}
当我在我的控制器中创建一个新的 Ticket 时:
public class BaseController : Controller
{
protected readonly IUnitOfWork UnitOfWork;
public BaseController(IUnitOfWork unitOfWork)
{
UnitOfWork = unitOfWork;
}
}
public class TicketController : BaseController
{
public TicketController(IUnitOfWork unitOfWork) : base(unitOfWork) { }
[HttpPost]
public ActionResult CreateTicket(CreateTicketVM viewModel)
{
// repopulate dropdowns incase we need to return view
// viewModel.Priorities is IEnumerable list
viewModel.Priorities = UnitOfWork.PriorityRepository.GetPriorities();
//validation code removed for brevity...
var ticket = new Ticket
{
RequestBy = !string.IsNullOrEmpty(viewModel.RequestBy) ? viewModel.RequestBy : User.Identity.GetUserId(),
PriorityId = viewModel.PriorityId != 0 ? viewModel.PriorityId : (int)PriorityLevel.Medium,
};
UnitOfWork.TicketRepository.Add(ticket);
}
}
现在,当我在调用 .Add(ticket)
后调试 var ticket
时,为什么它加载了相关导航 属性 Priority
而不是 Requester
导航 属性 尽管设置了 RequestBy
值?如您所见,我还没有针对任一导航属性定义任何 virtual
关键字?
Strangley 这只发生在 ApplicationUser
类型的所有导航属性中。即使不使用 virtual
关键字,所有其他导航属性似乎也会加载???
使用流利的 api 我定义了 RequestBy
FK 如下:
modelBuilder.Entity<Ticket>()
.HasRequired(x => x.Requester)
.WithMany()
.HasForeignKey(x => x.RequestBy);
下面是提供更多上下文的附加代码。
票证存储库:
public class TicketRepository : ITicketRepository
{
private readonly ApplicationDbContext _context;
public TicketRepository(ApplicationDbContext context)
{
_context = context;
}
public void Add(Ticket ticket)
{
_context.Ticket.Add(ticket);
}
}
优先存储库:
public class PriorityRepository : IPriorityRepository
{
private readonly ApplicationDbContext _context;
public PriorityRepository(ApplicationDbContext context)
{
_context = context;
}
public IEnumerable<Priority> GetPriorities()
{
return _context.Priority.ToList();
}
}
工作单元:
public class UnitOfWork : IUnitOfWork
{
private readonly ApplicationDbContext _context;
public ITicketRepository TicketRepository { get; private set; }
public IPriorityRepository PriorityRepository { get; private set; }
public UnitOfWork(ApplicationDbContext context)
{
_context = context;
TicketRepository = new TicketRepository(_context);
PriorityRepository = new PriorityRepository(_context);
}
public void Complete()
{
_context.SaveChanges();
}
}
两个导航 属性 都不应加载。您看到的很可能是所谓的导航 属性 修复功能的结果 - 如果实体已被上下文跟踪,EF 会更新引用它的实体的导航属性,即使您没有特别要求。
您可以使用 var _context = new YourDbContext();
局部变量而不是 _context
字段轻松验证这一点。或者像这样:
var ticket = new Ticket
{
RequestBy = !string.IsNullOrEmpty(viewModel.RequestBy) ? viewModel.RequestBy : User.Identity.GetUserId(),
PriorityId = viewModel.PriorityId != 0 ? viewModel.PriorityId : (int)PriorityLevel.Medium,
};
bool priorityLoaded = _context.Priority.Local.Any(e => e.Id == ticket.PriorityId);
bool userLoaded = _context.ApplicationUser.Local.Any(e => e.Id == ticket.RequestBy);
_context.Ticket.Add(ticket);
根据您的描述,priorityLoaded
应该是 true
而 userLoaded
- false
.