2016-04-01 4 views
1

Давайте предположим, что у меня есть две таблицы (SQL первого паттерна EF)Entity рамки нетерпеливый загрузки новых объектов против существующих объектов

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. Связанный с этим вопрос заключается в том, что если таблица 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

Просто убедитесь, что я правильно понимаю, что вы спрашиваете. Вы спрашиваете, почему вставка нового 'test1', связанного с существующим' test2', не заполняет свойство навигации 'test1.test2'' test2', когда вызывается 'SaveChanges'? –

+0

Я думаю, что я понимаю, почему он не заполняет навигационное свойство (эффективность?). Мой вопрос заключается в том, как получить функциональность «новой записи», чтобы больше походить на функциональность «таблицы запросов». При создании новой записи свойства навигации не заполняются, но при запросе с помощью linq через 'conn.table1' они заполняются. Я бы хотел, чтобы они были заполнены при создании новых записей. – user25064

+0

Самый простой способ заполнить все свойства навигации на вставке - это просто повторить запрос всего объекта, который вы только что вставили. Если у вас есть несколько свойств навигации, они будут более эффективными, чем заполнение их по отдельности. –

ответ

1

Вы ожидаете, что обычный объект C# будет выполнять ленивую загрузку. Этого не происходит. Для этого вам всегда нужен proxy object.

Ef создаст прокси, если вы используете

var t1 = conn.test1.Create(); 

Теперь вы увидите, что даже без вызова SaveChanges, test2 будет загружен только доступ к нему. То есть, если ленивая загрузка включена в контексте (который по умолчанию), а свойство test2 определяется как virtual.

+0

Большое вам спасибо за отличный ответ. – user25064

0

В принципе, вам просто нужно установить объект самостоятельно.

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

Я не знаю более чистого способа сделать это.

Смежные вопросы