实体框架渴望加载新对象与现有对象
本文关键字:对象 框架 渴望 加载 新对象 实体 | 更新日期: 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 = 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);
}
我理解为什么会发生这种事我的问题是我现在如何最好地填充这个"链接"以供使用?一种简单但不正确(过于低效)的方法是在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();
现在,您将看到即使不调用SaveChanges
,test2
也只能通过访问它来加载。也就是说,如果在上下文上启用了延迟加载(默认情况下),并且属性test2
定义为virtual
。
基本上,您只需要像这样自己设置对象。
t1.test2 = conn.test2s.FirstOrDefault(t => t.ID == t1.fk_test_2)
我不知道有什么更干净的方法可以做到这一点。