我有一个数据库模型,我想对它进行过滤(在运行时)其他属性。为此,我有一些方法,每个方法根据属性运行一个“ where”子句,并返回一个IQueryable。问题是该子句无法转换为SQL,因此查询不使用“ WHERE”语句运行,返回整个表,服务器正在执行过滤,这既缓慢又昂贵。
从日志中,我收到一条消息:
Microsoft.EntityFrameworkCore.Query:警告:LINQ表达式 “在哪里(新EntityId([ed] .EntityId).Id == __entityId_Id_1)”无法 进行翻译并将在本地进行评估。
我的问题是:我在这里正确吗?如果是的话,我下一步应该看什么?
主要功能
public static EntityDataDTO GetEntityByKey(this IQueryable<EntityDTO> query, IEntityId entityId, EntityTypeDTO type, string key)
{
return query
.HasEntity(entityId)
.HasType(type)
.HasKey(key)
.FirstOrDefault();
}
public static EntityDataDTO GetEntity(this IQueryable<EntityDTO> query, IEntityId entityId, EntityTypeDTO type)
{
return query
.HasEntity(entityId)
.HasType(type)
.FirstOrDefault();
}
子功能
public static IQueryable<EntityDDTO> HasType(this IQueryable<EntityDTO> query, EntityTypeDTO type)
{
return query.Where(ed => ed.Type == type);
}
public static IQueryable<EntityDTO> HasEntity(this IQueryable<EntityDTO> query, IEntityId entityId)
{
return query.Where(ed => ed.EntityId.Id == entityId.Id);
}
EntityDTO
public class EntityDTO
{
public int Id { get; set; }
public EntityTypeDTO Type { get; set; }
public string Key { get; set; }
public string Value { get; set; }
public IEntityId EntityId { get; set; }
public IPartnerId PartnerId { get; set; }
}
答案 0 :(得分:2)
我发现您发布的任何代码都没有问题。但是,您忽略了发布HasKey
方法的定义,因此我假设问题确实存在。
在任何情况下,警告都会准确告诉您问题代码是什么:new EntityId(ed.EntityId).Id
。找到那段代码并更正它。诸如调用新类型之类的东西无法转换为SQL,因此EF必须在内存中运行它。从技术上讲,您可以继续并仅允许EF执行此操作。但是,通常这表明您将要运行效率低下的查询,因此您应该寻找一种更好的方法,而不必在内存中运行该部分查询。
答案 1 :(得分:0)
您可以使用表达式谓词并为自己构建一个常见的可重用表达式的库。这是将其添加到EntityDTO的示例,请注意,它返回一个表达式,而不是实际的IQueryable / IEnumerable:
public partial class EntityDTO
{
public static Expression<Func<EntityDTO, bool>> HasType(EntityTypeDTO type)
{
return ed => ed.Type == type;
}
public static Expression<Func<EntityDTO, bool>> HasEntity(IEntityId entityId)
{
return ed => ed.EntityId.Id == entityId.Id;
}
}