我有一个案例,我查询的记录最多包含 20 个
Where()
子句(每个子句都是有条件添加的)加上以下内容:
IQueryable<Event> query;
query = dbContext.Events.FromSqlRaw("SELECT e.* FROM Events e INNER JOIN FreeTextTable(Events, *, {0}) as t on e.Id = t.[KEY]", queryText);
if (location != null)
query = query.WhereWithinRange(location, maxDistance ?? 0);
// lots more if ...
var listEvents = await query.ToListAsync();
问题是,它不会返回
Rank
伪列。因此,在运行上述查询后,我必须进行此附加查询以将排名与返回的 listEvents 联系起来。
var listRanks = await dbContext.Database.SqlQuery<FullTextTable>(
$"select * from FreeTextTable(Events, *, {queryText})")
.ToListAsync();
然后迭代
listRanks
并将任何匹配元素分配给 listEvents
中的记录。 Event
模型具有我用于此目的的 [NotMapped]
属性。
有没有办法在初始查询中获取
Rank
,这样我就不必运行此查询两次?如果不是,如果我正在做的事情是我能得到的最好结果,我是否应该从“listEvent”中获取 Event.Id
值列表,并在第二个查询中传递这些值,以便它只考虑 Id
所在的记录通过列表?
如果需要,这不是 DbContext 中的模型:
public class FullTextTable
{
/// <summary>
/// This corresponds to the primary key of the row in the table where the match is found.
/// </summary>
public int Key { get; set; }
/// <summary>
/// This indicates the relevance of the search result. A higher RANK value indicates a more
/// relevant result.<br/>
/// These will generally be in the range of 0 to 1000, but can be higher.
/// </summary>
public int Rank { get; set; }
/// <inheritdoc />
public override string ToString()
{
return $"{nameof(Key)}: {Key}, {nameof(Rank)}: {Rank}";
}
}
在 EF Core 8 中,您可以直接使用未映射的类型。
var query =
from e in dbContext.Events
join t in dbContext.Database.SqlQuery<FullTextTable>("SELECT t.* FROM FreeTextTable(Events, *, {0}) as t", queryText)
on e.Id = t.Key
select new Some {
e,
t.Rank
};
您需要将
WhereWithinRange
函数移动到连接之前,或者修改它们以采用包含排名的实际(非匿名)组合类型。
在旧版本的 EF Core 中,您需要在
OnModelCreating
中映射无密钥实体
modelBuilder.Entity<FullTextTable>().HasNoKey();
并使用
context.Set<>
代替。
join t in dbContext.Set<FullTextTable>().FromSql(.....