代码之家  ›  专栏  ›  技术社区  ›  adam78

实体框架-导航属性未加载?

  •  1
  • adam78  · 技术社区  · 7 年前

    我有以下实体:

    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; }
    }
    

    当我在我的控制器中创建如下新票据时:

     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);
        }
    }
    

    现在当我调试时 var ticket 通话后 .Add(ticket) Priority 而不是 Requester 导航属性,尽管 RequestBy virtual 针对任一导航属性的关键字?

    扼杀这种情况只发生在所有具有 ApplicationUser 事实上的 关键词???

    使用fluent api,我定义了 请求人 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();
        }
    }
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   Ivan Stoev    7 年前

    两个导航属性都不应加载。您看到的很可能是所谓导航属性修复功能的结果-如果实体已经被上下文跟踪,即使您没有特别请求,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 .