实体框架渴望加载新对象与现有对象

本文关键字:对象 框架 渴望 加载 新对象 实体 | 更新日期: 2024-05-18 11:51:53

让我们假设我有两个表(sql第一EF模式)

create table test1 (
    id int identity (1, 1),
    name1 varchar(64),
    fk_table2 int
);
create table test2 (
    id int identity (1, 1), 
    name2 varchar(64)
);

假设表test1中没有任何内容,test2中有一条记录包含id = 1name2 = 'hello'。由于链接未"加载",下面的代码段由于空引用而失败:

        using (var conn = new DatabaseObjects())
        {
            var t1 = new test1()
            {
                fk_test_2 = 1,
                name = "foo"
            };
            conn.test1.AddOrUpdate(t1);
            conn.SaveChanges();
            Console.WriteLine(t1.test2.name2);
        }

我理解为什么会发生这种事我的问题是我现在如何最好地填充这个"链接"以供使用?一种简单但不正确(过于低效)的方法是在Console.WriteLine调用之前添加对conn.test2.Load()的调用。一个相关的问题是,如果使用先前创建的行的id查询test1表,而不是创建新记录,则指向table2的链接将不会为空(它是"惰性加载的"?)。我不明白如何调和这种前后矛盾的行为。基本上,我希望在创建新记录后查询现有记录(其中存在指向test2表的链接)的行为。


编辑以处理下面的评论。有趣的是,当使用相同的conn对象实例重新查询时,导航属性仍然为null。但是,如果创建了一个新的DatabaseObjects实例,那么查询将返回一个填充了导航属性的对象。使用相同的示例

using (var conn = new DatabaseObjects())
{
    var t1 = new test1()
    {
        fk_test_2 = 1,
        name = "foo"
    };
    conn.test1.AddOrUpdate(t1);
    conn.SaveChanges();
    var t2 = (from e in conn.test1 where e.id == t1.id select e).First(); 
    // t2 navigation properties are STILL null
    var conn2 = new DatabaseObjects();
    var t3 = (from e in conn2.test1 where e.id == t1.id select e).First();
    // t3 navigation properties are NOT null
}

实体框架渴望加载新对象与现有对象

您期望一个普通的C#对象执行延迟加载。这种情况不会发生。为此,您总是需要一个代理对象。

如果您使用,Ef将创建一个代理

var t1 = conn.test1.Create();

现在,您将看到即使不调用SaveChangestest2也只能通过访问它来加载。也就是说,如果在上下文上启用了延迟加载(默认情况下),并且属性test2定义为virtual

基本上,您只需要像这样自己设置对象。

t1.test2 = conn.test2s.FirstOrDefault(t => t.ID == t1.fk_test_2)

我不知道有什么更干净的方法可以做到这一点。