2

我在使用 EF Code first 4.1 时遇到问题,并且可能不理解某些内容。

我的理解是,通过将关系(无论是集合还是单个对象)标记为虚拟,它们将按需延迟加载,因此我可以执行以下操作:

var page = context.Pages.Where(xxxx);

var department = page.Department; //load this on demand?
var name = department.Name; //null reference exception

但是,page.DepartmentId 已正确填充。此外,使用 context.Entry(page).Reference(p => p.Department).Load() 手动加载引用是可行的,但是拥有对象模型的全部意义在于不必在任何地方都如此痴迷。

public class Page
{
  public int DepartmentId { get; set; }
  public virtual Department { get; set; }
}

public class Department
{
  public virtual ICollection<Page> Pages { get; set; }
}

上下文 OnModelCreating

 modelBuilder.Entity<Page>().HasRequired(x => x.Department).WithMany(y => y.Pages).HasForeignKey(x => x.DepartmentId).WillCascadeOnDelete(false);

当然,我没有禁用延迟加载。

4

3 回答 3

4

您的项目中的某个地方可能有问题。我根据您的作品创建了简单的应用程序,一切正常。试试看,有什么不同。

首先,我的简单上下文:

class MyContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Page>().HasRequired(x => x.Department).WithMany(y => y.Pages).HasForeignKey(x => x.DepartmentId).WillCascadeOnDelete(false);
    }

    public IDbSet<Page> Pages { get; set; }
    public IDbSet<Department> Departments { get; set; }
}

将一些数据放入数据库的几乎虚拟初始化程序:

class TestInit : DropCreateDatabaseAlways<MyContext>
{
    protected override void Seed(MyContext context)
    {
        base.Seed(context);

        var newDepartment = context.Departments.Create();
        newDepartment.Name = "test";
        context.Departments.Add(newDepartment);

        var newPage = context.Pages.Create();
        newPage.Department = newDepartment;
        context.Pages.Add(newPage);

        context.SaveChanges();

        // leaving nothing in context
        var fullContext = (context as IObjectContextAdapter).ObjectContext;
        fullContext.Detach(newDepartment);
        fullContext.Detach(newPage);
    }
}

还有你的课:

public class Page
{
    public int ID { get; set; }
    public int DepartmentId { get; set; }
    public virtual Department Department { get; set; }
}

public class Department
{
    public int ID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Page> Pages { get; set; }
}

现在测试: Database.SetInitializer(new TestInit());

using (MyContext context = new MyContext())
{
    Console.WriteLine(context.Pages.Local.Count);
    Console.WriteLine(context.Departments.Local.Count);

    var page = context.Pages.First();
    Console.WriteLine(page.GetType().FullName);
    Console.WriteLine(page.Department.Name);
}

您应该看到(代理哈希可能会有点不同):

0
0
System.Data.Entity.DynamicProxies.Page_6D31E91F3B1E767826A19855D3A934B59F85AC161548E4761283C85824520E1D
test

可以肯定的是,前两个零是上下文中没有实体的。Page 类的类型应该是代理,如果是程序本身的类型,则不会生成代理。可能它已关闭或某些东西不是虚拟的等。最后一行是部门的实际名称。

当我运行程序时,除了其他查询之外,还有:

SELECT 
[Extent1].[ID] AS [ID], 
[Extent1].[Name] AS [Name]
FROM [dbo].[Departments] AS [Extent1]
WHERE [Extent1].[ID] = @EntityKeyValue1

被发送到数据库。

于 2012-01-07T08:05:17.673 回答
1

我弄清楚我的情况出了什么问题。我将默认构造函数标记为私有,因此 ef 没有为我生成代理。

感谢大家。

于 2012-01-07T16:29:58.880 回答
0

为 Page 尝试以下模型,看看它是否有帮助

public class Page
{
    public int DepartmentId { get; set; }
    public virtual Department Department { get; set; }
}

您缺少 Department 的变量。希望它现在有效

于 2012-01-07T08:12:53.040 回答