#c# #entity-framework
#c# #entity-framework
Вопрос:
Entity Framework генерирует недопустимый SQL-запрос для следующего запроса LINQ:
Car[] results = this.DbContext.Cars
.Where(x => !x.ParentId.HasValue) // also for x.ParentId == null
.ToArray();
Моим свойством ParentID является nullable int, внешний ключ к той же таблице (свойство Id). Мои результаты представляют собой пустой массив, но этого не должно быть. Я использовал аналогичный запрос (проверяя, что свойство nullable не имеет значения), используя другие таблицы, и он работал просто отлично. В этом случае разница в том, что ParentID является внешним ключом, а таблица базы данных использует TPH. Это ошибка или я допустил какие-то ошибки? Почему EF вообще игнорирует свойство nullable? Моя конфигурация и сгенерированный SQL с помощью EF (именование только для примера, например, «Car»):
Конфигурация контекста:
// TPH (Table per Hierarchy)
modelBuilder.Entity<Car>()
.Map<CarA>(x => x.Requires("type").HasValue(1))
.Map<CarB>(x => x.Requires("type").HasValue(2))
.Map<CarC>(x => x.Requires("type").HasValue(3))
.Map<CarD>(x => x.Requires("type").HasValue(4));
// parent child relationship
modelBuilder.Entity<Car>()
.HasMany(x => x.Children)
.WithRequired()
.HasForeignKey(child => child.ParentId);
Свойства моего класса:
[Column("parent_id")]
public int? ParentId { get; set; }
public virtual List<Car> Children { get; set; }
для:
Car[] results = this.DbContext.Cars
.Where(x => !x.ParentId.HasValue)
.ToArray();
Я получаю пустой результат с сгенерированным SQL:
SELECT
CAST(NULL AS int) AS [C1],
CAST(NULL AS int) AS [C2],
...
...
...
CAST(NULL AS decimal(18,2)) AS [C20],
CAST(NULL AS datetime2) AS [C21]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
WHERE 1 = 0
Но это должно быть:
...
...
WHERE [Extent1].[car] IS NULL
для:
var results = this.DbContext.Cars
.Where(x => x.ParentId.HasValue)
.ToArray();
Я получаю все объекты (родительский идентификатор игнорируется) с сгенерированным SQL:
SELECT
[Extent1].[type] AS [type],
[Extent1].[id] AS [id],
[Extent1].[parent_id] AS [parent_id],
[Extent1].[name] AS [name],
...
...
...
FROM [dbo].[car] AS [Extent1]
WHERE [Extent1].[type] IN (1,2,3,4)
Протестировано на EF6 6.0.2 / 6.1.1 и MS SQL Server.
Ответ №1:
Вау… это забавное поведение, но решение довольно простое. У вас есть свойство внешнего ключа с нулевым значением, но вы определили связь как требуется. Просто измените
modelBuilder.Entity<Car>()
.HasMany(x => x.Children)
.WithRequired()
.HasForeignKey(child => child.ParentId);
Для
modelBuilder.Entity<Car>()
.HasMany(x => x.Children)
.WithOptional()
.HasForeignKey(child => child.ParentId);
И это будет работать.