简体   繁体   English

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

[英]Entity framework eager loading new objects vs existing objects

Let's assume that I have two tables (sql first EF pattern)假设我有两个表(sql first 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)
);

Let's assume that we start with nothing in table test1 and one record in test2 with id = 1 and name2 = 'hello' .假设我们从表test1任何内容和test2一条记录开始, id = 1name2 = 'hello' The code snippet below fails due to a null reference as the link is not "loaded":由于链接未“加载”,以下代码段因空引用而失败:

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

I understand why this is happening.我明白为什么会这样。 My question is how best do I now populate this "link" for it to be used?我的问题是我现在如何最好地填充这个“链接”以供使用? A simple but incorrect (overly inefficient) way is by adding a call to conn.test2.Load() before the Console.WriteLine call.一个简单但不正确(效率太低)的方法是在Console.WriteLine调用之前添加对conn.test2.Load()的调用。 A related question is, if the test1 table is queried with an id of a previously created row as opposed to creating a new record, the link to table2 will not be null (it is "lazy loaded"?).一个相关的问题是,如果使用先前创建的行的 id 查询test1表而不是创建新记录,则table2的链接不会为空(它是“延迟加载”?)。 I don't understand how to reconcile this inconsistent behavior.我不明白如何调和这种不一致的行为。 Basically, I would like the behavior of querying an existing record where the link to the test2 table exists after creating new records.基本上,我希望在创建新记录后查询存在指向test2表的链接的现有记录的行为。


Edit to address comments below.编辑以解决下面的评论。 Interestingly, when re-querying with the same conn object instance, the navigation properties are still null.有趣的是,当使用相同的conn对象实例重新查询时,导航属性仍然​​为空。 But, if a new DatabaseObjects instance is created, the query returns an object with the navigation properties populated.但是,如果创建了一个新的DatabaseObjects实例,该查询将返回一个填充了导航属性的对象。 Using the same example使用相同的例子

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
}

You expect a normal C# object to perform lazy loading.您期望一个普通的 C# 对象执行延迟加载。 That doesn't happen.那不会发生。 You always need a proxy object for that.为此,您始终需要一个代理对象

Ef will create a proxy if you use如果您使用 Ef 将创建一个代理

var t1 = conn.test1.Create();

Now you'll see that even without calling SaveChanges , test2 will be loaded only by accessing it.现在您会看到,即使没有调用SaveChangestest2也只能通过访问它来加载。 That is, if lazy loading is enabled on the context (which it is by default) and property test2 is defined as virtual .也就是说,如果在上下文中启用了延迟加载(默认情况下是这样)并且属性test2被定义为virtual

Basically you just have to set the object yourself like this.基本上你只需要像这样自己设置对象。

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

I'm not aware of cleaner way to do this.我不知道这样做的更清洁的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM