2016-04-01 81 views
1

让我们假设我有两个表(SQL第一EF模式)实体框架立即加载新对象VS现有对象

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

假设,我们开始没有在表test1test2id = 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()的呼叫。一个相关的问题是,如果test1表中查询的是以前创建的行的ID而不是创建新记录,则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

只是为了确保我明白你问的是正确的。你问为什么当调用SaveChanges时,插入一个连接到现有'test2'的新'test1'不会将'test1.test2'导航属性填充到'test2'? –

+0

我想我明白为什么它不填充导航属性(效率?)。我的问题更多地是关于如何使“新记录”功能更像“查询表”功能。创建新记录时,导航属性不会填充,但在通过'conn.table1'查询linq时会填充它们。我希望在创建新记录时填充它们。 – user25064

+0

插入所有导航属性的最简单方法可能是重新查询刚插入的整个对象。如果您有多个导航属性,它将比单独填充这些导航属性效率更高。 –

回答

1

您希望正常的C#对象执行延迟加载。那不会发生。你总是需要一个proxy object

如果使用

var t1 = conn.test1.Create(); 

现在你会看到即使没有调用SaveChangestest2将只通过访问加载Ef中会创建一个代理。也就是说,如果在上下文中启用了延迟加载(默认情况下为启用),并且属性test2定义为virtual

+0

非常感谢你的回答。 – user25064

0

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

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

我不知道更干净的方式来做到这一点。