我们假设我有两个表(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 = 1
和name2 = '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
}
答案 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)
我不知道更清洁的方法。