Исключить производные объекты из запросов к базовому классу - PullRequest
0 голосов
/ 30 октября 2018

У меня есть этот DbContext:

public class DataContext : DbContext
{
    public DbSet<Base> Bases {get;set}
    public DbSet<Sub> Subs {get;set}
}

Sub является подклассом Base.

Когда я запрашиваю список базовых сущностей, например:

Context.Bases.ToListAsync()

Возвращает мне все сущности, либо Base, либо Sub.

Как я могу сконфигурировать контекст моей модели, чтобы получать только сущности типа Base, а не те, которые являются ее производными.

Ответы [ 3 ]

0 голосов
/ 30 октября 2018

Вы должны использовать OfType<T>:

var basesOnly = await _context.Bases.OfType<Base>().ToListAsync();

UPDATE

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

var basesOnly = await _context.Bases.Where(x => !(x is Sub)).ToListAsync();
0 голосов
/ 30 октября 2018

Лучшее (или наименее худшее) решение, которое я нашел, - это непосредственное использование свойства shadow:

Context.Bases.Where(b => EF.Property<string>(b, "Discriminator") == "Base")).ToListAsync();

Это работает, но нужно время от времени повторять каждый раз, когда мне нужно запросить Bases. Я бы предпочел решение в методе OnModelCreating.

Я приму этот ответ, если кто-то еще не найдет лучшего решения.

0 голосов
/ 30 октября 2018

Как я могу настроить контекст моей модели, чтобы получать только те объекты, которые базового типа, а не те, которые происходят от него.

Вы не можете. Каждый Sub является База. Таким образом, запрос всех баз включает в себя все сабвуферы. Например, следующий код должен быть успешным:

Base b = db.Bases.Where(i => i.Id == 1).Single();
if (b is Sub)
begin
  Sub s = (Sub)b;
  . . .
end
else //other Sub
begin
  Sub2 s = (Sub2)b;
  . . .

end

Вы можете получить анонимный тип только с помощью свойств базового класса.

И, задавая этот вопрос предполагает , что наследование может не подходить для вашего сценария.

Если вы хотите, чтобы он выбирал сущности типа Base, но не , а не подтипа Sub, то вы можете сделать это с помощью запроса:

var q = from b in db.Bases
        where !(b is Sub)
        select b;

Что означает:

SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[Size]
FROM [Bases] AS [b]
WHERE [b].[Discriminator] IN (N'Sub', N'Base') 
AND NOT ([b].[Discriminator] = N'Sub')

Но вы не можете (в настоящее время) исключить все подтипы, не перечислив их. Например, этот запрос:

var q2 = from b in db.Bases
         where b.GetType() == typeof(Base)
         select b;

Не будет полностью переведен в SQL и отфильтрует подтипы на клиенте.

...