Я использую EF Core 2.2 .FromSql () для запуска полнотекстового поиска запроса с использованием предиката CONTAINS ().
Iвыполнять поиск по всем полнотекстовым индексированным столбцам.
Согласно документации ( ссылка ), для выполнения запроса полнотекстового поиска можно указать:
- column_name
- (column_list)
- "*" (запрос ищет все полнотекстовые индексированные столбцы)
Есть метод ' EF.Functions.Contains () ', но позволяет вводить только одну propertyReference :
Expression<Func<T, bool>> searchPredicate = x =>
EF.Functions.Contains(EF.Property<string>(x, "FirstName"), searchKeyword);
Я могу построить запрос, используя OR оператор, подобный следующему:
Expression<Func<T, bool>> searchPredicate = x =>
EF.Functions.Contains(EF.Property<string>(x, "FirstName"), searchKeyword) ||
EF.Functions.Contains(EF.Property<string>(x, "LastName"), searchKeyword);
Но, глядя в профилировщик, он создает следующий запрос, который нежелателен :
SELECT [x].[Id],
[x].[FirstName],
[x].[LastName],
[x].[Address]
FROM [Users] AS [x]
WHERE (CONTAINS([x].[FirstName], 'John' /* @__searchKeyword_1 */))
OR (CONTAINS([x].[LastName], 'John' /* @__searchKeyword_1 */))
Итак, я должен использовать пользовательскийзапрос в .FromSql () , чтобы выполнить поиск по всем полнотекстовым индексированным столбцам, например:
var customQuery = "SELECT * FROM Users WHERE CONTAINS(*, '\"John\"')";
var users = context.Users.FromSql(customQuery);
Ожидаемый запрос:
SELECT * FROM Users WHERE CONTAINS(*, '\"John\"');
Фактический запрос:
SELECT [p].[Id],
[p].[FirstName],
[p].[LastName],
[p.Address].[Id],
[p.Address].[Street],
[p.Address].[StreetNumber]
FROM (SELECT * FROM Users WHERE CONTAINS(*, '\"John\"')) AS [p]
LEFT JOIN [Users] AS [p.Address]
ON [p].[Id] = [p.Address].[Id]
Entity, ValueObject и OnModelCreating () выглядит следующим образом:
public class User : IEntity
{
public Guid Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Address Address { get; set; }
}
public class Address: IValueObject
{
public string Street { get; set; }
public string StreetNumber { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>().ToTable("Users");
modelBuilder.Entity<User>().OwnsOne(e => e.Address);
}
Я сохраняю Address ValueObject в той же таблице Users с .OwnsOne () .
Использование .FromSql () на другом объекте, в котором нет ValueObject, работает нормально и не включает в запрос LEFT JOIN.
Что следует делатьЯ делаю, чтобы пропустить LEFT JOIN в запросе и правильно выполнить полнотекстовый поиск?