在计算属性上使用contains时,OData v4过滤器查询失败

时间:2016-01-07 18:07:31

标签: c# asp.net-web-api entity-framework-6 odata

所以我有一个代码第一个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(&#39; smith&)的OData查询时#39;))我收到BadRequest回复。我在WebAPI get方法中验证了它是否成功从数据库中获取结果,但它发回BadRequest错误。

它肯定与FullName字段有关,要么是计算字段,要么是因为它具有NotMapped属性。当我将OData查询更改为 $ filter = contains(tolower(LastName),tolower(&#39; smith&#39;))时,它可以正常工作。我也尝试使用显示名称&#34; Full Name&#34;在查询中而不是&#34; FullName&#34;那也没有用。

我是否需要做些什么才能让OData在计算或未映射的字段中发挥出色?

2 个答案:

答案 0 :(得分:1)

在您的ContactsController上实现OData function,它接受​​一个字符串进行比较,并返回已过滤的联系人集。类似的东西:

    [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,函数必须在内存中执行过滤。

答案 1 :(得分:1)

@ lencharest的答案将为您提供正确的结果,但请记住,您将把所有数据拉入内存以执行过滤。如果你有100个联系人,那不是什么大不了的事,但如果你有大量的联系人呢?

我会在DB中创建一个包含FullName逻辑的视图。然后,将此视图公开为您的实体。然后,过滤可以在数据库中进行,您可以拥有一个完全可查询的实体。

<强>更新 稍微考虑一下,更好的方法是FullName的表中的计算列。假设您最终可能需要支持其他动词(POST,PATCH等等),在表中使用完整的实体定义将使事情保持直截了当。通过实现OData函数,您基本上放弃了可查询的odata模型。它们有它们的位置,但通常用于复杂的多实体操作,而不是对基本实体的单个属性实现过滤。