Ядро EF: загрузка связанных объектов только как идентификаторов

#c# #entity-framework-core

#c# #entity-framework-core

Вопрос:

Я не уверен, что то, чего я хочу, — это то, чего следует ожидать от EF, но я думаю, что я видел это в других ORM, и это должно быть довольно распространенным явлением для решения в EF — поэтому я спрашиваю, было ли это.

Я хочу иметь возможность быстро загружать объекты внешнего ключа при запросе EF, но только их идентификаторы, так как другая часть объектов будет загружена намного позже.

У меня есть:

 class A {
   public int Id { get; set; }
   public B B { get; set; }
}

class B {
   public int Id { get; set; }
   // .... more properties
} 
  

И веб-API, который должен возвращать список всех As с этой моделью представления:

 class AViewModel {
   public int Id { get; set; }
   public int BId { get; set; }
}
  

Я хочу убедиться, что я не включаю соединение с таблицей B при запросе — по соображениям производительности. Я также использую automapper для отображения от A до AViewModel .

В настоящее время лучший способ, который я нашел для этого, — это:

 var a = context.As;
var aList = a.Select(x => new { model = x, bid = x.B.Id }).ToList();
return Ok(mapper.Map<List<AViewModel>(aList));
  

К сожалению, это означает, что я должен добавить отображение из new { model = x, bid = x.B.Id } в AViewModel , что действительно нетрадиционно.
Я бы предпочел просто иметь возможность писать:

 var a = context.As;
var aList = a.ToList();
return Ok(mapper.Map<List<AViewModel>(aList));
  

Но в данном случае это не удается с NullReferenceException , потому что каждый элемент aList имеет B свойство null .

Я мог бы написать context.As.Include(x => x.B) , но это присоединится к таблице B, чего я хотел бы избежать.

Я думаю, что я видел, что некоторые ORM могут заполнять B объекты пустыми объектами, за исключением идентификаторов — и это поведение, которое я ищу в EF. Может ли это сделать это?

Если нет, может быть, можно предложить более приятный способ решения проблемы? может быть, я могу как-то исправить это с помощью ленивых прокси?

Ответ №1:

Поместите свойство ForeignKey в класс A:

 class A {
   public int Id { get; set; }

   public int BId {get; set;}

   [ForeignKey("BId")] //can do this in the fluent API instead
   public virtual B B { get; set; }
}
  

Тогда вы можете просто использовать класс A в сопоставлении без необходимости загружать объект B.

Комментарии:

1. Это кратко и правильно. Просто хотел добавить, что даже нет необходимости настраивать отношение явно через атрибут / fluent API, если вы следуете соглашению об именовании, которое вы делаете в своем примере. Ссылка .

2. Я не на 100% доволен этим, поскольку это вынуждает меня иметь свойство, которое я нигде не использую, кроме как в Automapper конфигурации, но это правда, что это правильный и, вероятно, самый приятный способ получить то, что я хочу. Это также удивило меня, насколько это было просто, я не думал об этом раньше и ожидал более сложного ответа. Спасибо