我在使用EF Code 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(页面)手动加载引用.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; }
}
context OnModelCreating
modelBuilder.Entity<Page>().HasRequired(x => x.Department).WithMany(y => y.Pages).HasForeignKey(x => x.DepartmentId).WillCascadeOnDelete(false);
当然,我没有禁用延迟加载。
答案 0 :(得分: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类的类型应该是proxy,如果它是程序本身的类型,则不生成代理。可能它已关闭或某些东西不是虚拟等。最后一行是部门的实际名称。
当我运行程序时,除了其他查询之外,还有:
SELECT
[Extent1].[ID] AS [ID],
[Extent1].[Name] AS [Name]
FROM [dbo].[Departments] AS [Extent1]
WHERE [Extent1].[ID] = @EntityKeyValue1
被发送到数据库。
答案 1 :(得分:1)
我弄清楚我的情况出了什么问题。我将默认构造函数标记为私有,因此ef没有为我生成代理。
谢谢大家。
答案 2 :(得分:0)
为Page尝试以下模型并查看是否有帮助
public class Page
{
public int DepartmentId { get; set; }
public virtual Department Department { get; set; }
}
您缺少Department的变量。希望它现在有效