2016-07-14 2 views
0

мне нужно сделать что-то вроде ...Почему EF удаляет дочерние объекты при отсоединении?

  1. получить контекст дб (UtilitiesContext)
  2. запрос это для некоторых данных (Подписанные Директории)
  3. тянуть также детей из БД, когда я тянуть компании WD (AdditionalData)
  4. Dispose контекста
  5. Продолжать использовать объекты

...

// step 1 
using (var db = new UtilitiesContext(false)) 
{ 
    var jsonSettings = new JsonSerializerSettings { MaxDepth = 2, ReferenceLoopHandling = ReferenceLoopHandling.Ignore }; 

    // step 2 
    var dirs = db.GetAll<WatchedDirectory>(); 

    // step 3 (lazy load and serialize the WD and its additional data) 
    log.Debug(JsonConvert.SerializeObject(dirs, jsonSettings)); 

    foreach (var d in dirs) 
    { 
     try 
     { 
      log.Debug(" Initialising monitoring for path " + d.UNCPath); 

      // detach the object and its data items from the db 
      db.Detach(d); 
      d.AdditionalData.ForEach(i => db.Detach(i)); 

      // here the AdditionalData property serialises an empty array 
      log.Debug(JsonConvert.SerializeObject(d, jsonSettings)); 

// step 4 happens down here 

Моя проблема заключается в том, что я получаю все данные, которые я хочу на выходе первого журнала (линия, обозначенная шаг 3) А потом, когда я повторяю, что сбор ребенок ушел, и все, что я делал, было отсоединять сущности из контекста.

Мой метод отсоединение выглядит так ...

public void Detach(object entity) 
{ 
    Entry(entity).State = EntityState.Detached; 
} 
+0

Если вы собираетесь использовать контекст, вы должны сначала сопоставить их с DTO. Я считаю, что у вас будет гораздо больше проблем, чем просто, если вы будете следовать своему текущему пути. Работа с объектами сущности вне контекстной области задает проблемы. –

+0

Yeh Я это рассматривал ... это очень простые объекты, хотя я думал, что это возможно, чтобы сохранить дублирование кода. – War

+0

Я пытался сделать подобное в прошлом, и он ВСЕГДА возвращается, чтобы укусить вас в задницу , теперь проще делать сопоставления, чем работать над более поздним моментом времени, когда вам нужно переписать гораздо больший объем кода, когда он, наконец, взорвется на вас. –

ответ

0

EF смешной зверь, это окончательное излечение для отсоединение объект из контекста ...

var jsonSettings = new JsonSerializerSettings { MaxDepth = 2, ReferenceLoopHandling = ReferenceLoopHandling.Ignore }; 
var dirs = JsonConvert.DeserializeObject<List<WatchedDirectory>>(JsonConvert.SerializeObject(db.GetAll<WatchedDirectory>().ToList(), jsonSettings)); 

Есть, вероятно, лучшие практики для этого, но этот бык в китайском магазине решил решить мою проблему.

0

Когда вы отсоединяете родительский объект от контекста, вы больше не можете использовать ленивую загрузку дочерних объектов (что в вашем случае вы никогда не должны делать так или иначе, b/c производительность сильно пострадает). Более эффективный метод заключается в том, чтобы использовать include() для загрузки требуемых детей вперед. Это позволит сэкономить дополнительные вызовы в db. Например, если у каждого родителя есть 2 ребенка, вы должны сделать 1 вызов для родителя и еще 2 вызова для каждого ребенка. Очень неэффективно.

Ваш метод сериализации что-то для десериализации что-то плохой способ получить DTO. Вы должны делать сопоставление (возможно, с Automapper) или отключать обработку EF-прокси и ленивую загрузку, что имеет аналогичный эффект.

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