[英]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 = 1
和name2 = '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.现在您会看到,即使没有调用SaveChanges
, test2
也只能通过访问它来加载。 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.