具有现有数据库的实体框架 - 导航属性不起作用

时间:2015-11-24 17:00:08

标签: entity-framework entity-framework-6

我有一组实体:

public class Board : EntityBase
{
    public ICollection<Slot> Slots { get; set; }
}

public class Slot : EntityBase
{        
    public ICollection<Card> Cards { get; set; }

    public string Header { get; set; }

    public int BoardId { get; set; }
}

public class Card : EntityBase
{        
    public string Description { get; set; }

    public string Title { get; set; }

    public int SlotId { get; set; }
}

以及相应的数据库表:

CREATE TABLE Boards
(
    Id INT PRIMARY KEY,
    UserId INT NOT NULL,
    CONSTRAINT FK_Users_UserId FOREIGN KEY (UserId)
    REFERENCES Users(Id)
)

CREATE TABLE Slots
(
    Id INT PRIMARY KEY,
    Header NVARCHAR(MAX),
    BoardId INT NOT NULL,
    CONSTRAINT FK_Slots_BoardId FOREIGN KEY (BoardId)
    REFERENCES Boards(Id)
)

CREATE TABLE Cards
(
    Id INT PRIMARY KEY,
    Title NVARCHAR(MAX),
    Description NVARCHAR(MAX),
    SlotId INT NOT NULL,
    CONSTRAINT FK_Cards_SlotId FOREIGN KEY (SlotId)
    REFERENCES Slots(Id)
)

尝试从数据库中检索并实例化“Board”时,它不会填充“Slots”属性。似乎Entity框架无法识别出存在外键约束。我的理解是,如果属性不是虚拟的,它们将被急切加载,如果我错了请纠正我。

是否存在我缺少/需要设置以使导航属性有效的内容?

主叫代码:

Context.Boards.Find(id);

我的DbContext:

public class SampleContext : DbContext, IUnitOfWork
{
    public SampleContext() : base("name=SampleApplication") { }

    public void Save()
    {
        SaveChanges();
    }

    public DbSet<Board> Boards { get; set; }
    public DbSet<Card> Cards { get; set; }
    public DbSet<Slot> Slots { get; set; }
}

我已将导航属性设为虚拟并按如下方式加载,现在正在运行:

public Board GetBoard(int id)
{            
    var board = Context.Boards.Find(id);

    Context.Entry(board)
        .Collection(b => b.Slots)
        .Load();

    return board;
}

2 个答案:

答案 0 :(得分:1)

您必须使EF代理的导航属性virtual能够覆盖它。

关于非虚拟属性的加载是非常错误的。他们不。您必须使用Include方法显式加载它们。请在此处阅读:https://msdn.microsoft.com/en-us/data/jj574232.aspx

答案 1 :(得分:1)

当您包含虚拟关键字时,延迟加载不会自动发生。您需要使用包含()方法

类似

var graph = context.Boards.Include("Slots");
foreach(var board in graph)
{
   Console.Writeline("Slot value {0}",board.Slots);
}