在计算属性上使用包含时,OData v4筛选器查询失败
本文关键字:v4 OData 筛选 失败 查询 包含时 属性 计算 | 更新日期: 2023-09-27 18:29:19
所以我有一个代码优先的EF 6层,它的Contact类为:
public class Contact
{
[Key]
public int Id { get; set; }
[MaxLength(50)]
public string Prefix { get; set; }
[MaxLength(50)]
public string Suffix { get; set; }
[MaxLength(50)]
public string FirstName { get; set; }
[MaxLength(50)]
public string MiddleName { get; set; }
[MaxLength(50)]
public string LastName { get; set; }
[NotMapped]
[DisplayName("Full Name")]
public string FullName
{
get
{
string tempName =
(!string.IsNullOrEmpty(Prefix) ? Prefix + " " : "") +
(!string.IsNullOrEmpty(FirstName) ? FirstName + " " : "") +
(!string.IsNullOrEmpty(MiddleName) ? MiddleName + " " : "") +
(!string.IsNullOrEmpty(LastName) ? LastName + " " : "") +
(!string.IsNullOrEmpty(Suffix) ? Suffix + " " : "");
return tempName.Trim();
}
}
[MaxLength(50)]
public string JobTitle { get; set; }
public bool? Primary { get; set; }
public bool? Inactive { get; set; }
public int? Customer_Id { get; set; }
[ForeignKey("Customer_Id")]
public virtual Customer Customer { get; set; }
public virtual ICollection<Email> Emails { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
public virtual ICollection<PhoneNumber> PhoneNumbers { get; set; }
public virtual ICollection<Note> Notes { get; set; }
}
我运行了一个ASP.NET Web API 2服务,该服务提供联系人列表,但当我执行$filter=contains(tolower(FullName),tolower('smith'))的OData查询时,我会得到BadRequest响应。我在WebAPI get方法中验证了它成功地从数据库中获取结果,但它发回了BadRequest错误。
它肯定与FullName字段有关,要么是计算字段,要么是因为它具有NotMapped属性。当我将OData查询更改为$filter=contains(tolower(LastName),tolower('smith'))时,它可以正常工作。我还尝试在查询中使用显示名称"FullName"而不是"FullName",但这也不起作用。
我需要做些什么来让OData在计算或未映射的字段中表现得很好吗?
在ContactsController上实现一个OData函数,该函数接受一个字符串进行比较,并返回过滤后的Contacts集。类似于:
[HttpGet]
[ODataRoute("Contacts/Default.FullNameContains(value={value})")]
public IHttpActionResult FullNameContains(string value)
{
value = value.ToLower();
return Ok(db.Contacts.ToList().Where(c => c.FullName.Contains(value)));
}
因为FullName
是计算出来的,所以函数必须在内存中执行过滤。
@lencharest的答案将给出正确的结果,但请记住,为了执行筛选,您将把所有数据拉入内存。如果你有100个联系人,那没什么大不了的,但如果你有很多联系人呢?
我会在DB中创建一个包含FullName逻辑的视图。然后,将此视图作为实体公开。然后,过滤可以在数据库中进行,并且您可以拥有一个完全可查询的实体。
更新:再仔细考虑一下,一个更好的方法是在表中为FullName计算一列。假设您最终可能需要支持其他动词(POST、PATCH等…),那么在表中有完整的实体定义将使事情向前发展。通过实现OData函数,您基本上放弃了可查询的OData模型。它们有自己的位置,但通常用于复杂的多实体操作,而不是在基本实体的单个属性上实现过滤器。