延迟加载不起作用

发布于 2024-12-19 02:50:02 字数 889 浏览 4 评论 0原文

我在使用 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; }
}

context OnModelCreating

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

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

I'm having trouble using EF Code first 4.1 and am probably not understanding something.

My understanding is that by marking relationships (whether collections or single objects) as virtual, they will be lazy loaded on demand, so I could do something like:

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

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

page.DepartmentId is populated correctly, however. In addition, manual loading the reference with context.Entry(page).Reference(p => p.Department).Load() works, but the whole point of having an object model is to not have to obsessively do that everywhere.

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

I've not disabled lazy loading, of course.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

放肆 2024-12-26 02:50:02

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

首先,我的简单上下文:

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

发送到数据库。

there's probably something wrong on some place in your project. I created simple application based on your pieces and everything works fine. Try it and see, what's different.

First, my simple context:

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

Almost dummy initializer to put some data into database:

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

And your classes:

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

Now the test:
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);
}

You should see (the proxy hash will be probably little bit different):

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

First two zeros are there to be sure, that there are no entities in context. The type of Page class should be proxy, if it's the type from program itself, proxies are not being generated. Probably it's turned off or something is not virtual etc. Last line is actual name of department.

When I run the program, besides other queries, also:

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

is sent to database.

恋竹姑娘 2024-12-26 02:50:02

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

谢谢大家。

I figured out what was wrong in my situation. I marked the default constructor as private so ef was not generating the proxies for me.

thanks everyone.

我早已燃尽 2024-12-26 02:50:02

尝试使用以下页面模型,看看它是否有帮助。

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

您缺少部门变量。希望现在有效

Try the following model for Page and see if it helps

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

You are missing the variable for Department. Hope it works now

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文