实体框架急切地加载新对象与现有对象

时间:2016-04-01 19:36:09

标签: c# entity-framework tsql

我们假设我有两个表(sql first EF pattern)

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

我明白为什么会这样。 我的问题是我现在最好填充这个“链接”以供其使用?一种简单但不正确(过于低效)的方式是在conn.test2.Load()调用之前添加对Console.WriteLine的调用。一个相关的问题是,如果使用先前创建的行的id查询test1表而不是创建新记录,则table2的链接将不为空(它是“延迟加载” ?)。我不明白如何调和这种不一致的行为。基本上,我想查询创建新记录后存在test2表链接的现有记录的行为。

修改以解决以下评论。有趣的是,当使用相同的conn对象实例重新查询时,导航属性仍为空。但是,如果创建了新的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
}

2 个答案:

答案 0 :(得分:1)

您希望普通的C#对象执行延迟加载。这并没有发生。你总是需要proxy object

如果您使用

,Ef将创建代理
var t1 = conn.test1.Create();

现在,即使没有调用SaveChanges ,您也会看到test2只会通过访问它来加载。也就是说,如果在上下文中启用了延迟加载(默认情况下是这样),则属性test2被定义为virtual

答案 1 :(得分:0)

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

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

我不知道更清洁的方法。