我定义了一个模仿$ search的odata函数,该函数在最近的核心版本中尚不支持。我想返回核心实体以及扩展的实体,该实体将转换为返回的json值数组中每个Person上的js对象。
我在odata/People/MyNS.Find(text='john', orderby='CreatedOn')?$expand=CurrentWork
上尝试了CurrentWork在People上,但是那没用。
关于如何执行此操作的想法?
// my controller code for the function
[HttpGet]
public ActionResult<ICollection<People>> Find([FromODataUri] string text,
[FromODataUri] string orderBy)
{
if (text == null || text.Length == 0)
return Get().ToList();
if (orderBy == null || orderBy.Length == 0)
orderBy = "CreatedOn";
return _db.People
.Where(p => p.FirstName.Contains(text)
|| p.LastName.Contains(text)
|| p.Nickname.Contains(text))
.OrderBy(orderBy)
.Take(5000)
.ToList();
}
在不起作用的情况下常规扩展CurrentWork可以很好地工作,例如odata/People?$expand=CurrentWork
。
答案 0 :(得分:1)
通过查看Linq查询,它仅获取People数据,而不获取其任何子集合。您应该使用Include
来获取子集合以及父实体的数据,如下所示。详细了解如何加载相关实体here。
// my controller code for the function
[HttpGet]
public ActionResult<ICollection<People>> Find([FromODataUri] string text,
[FromODataUri] string orderBy)
{
if (text == null || text.Length == 0)
return Get().ToList();
if (orderBy == null || orderBy.Length == 0)
orderBy = "CreatedOn";
return _db.People
.Where(p => p.FirstName.Contains(text)
|| p.LastName.Contains(text)
|| p.Nickname.Contains(text))
.Include(p => p.CurrentWork) // I have added this line
.OrderBy(orderBy)
.Take(5000)
.ToList();
}
注意:您仍然需要使用$ expand = CurrentWork作为查询字符串。如果没有此查询字符串,服务器将在向客户端发送响应之前删除子集合。
答案 1 :(得分:0)
这就是我最后想出的。我注意到所包含的实体正在从数据库中提取大量数据,因此我通过具体说明大大降低了这种提取。包括只是拉了一切,我不能直接降低Include
,所以我不得不使用Select
。
[HttpGet]
public IOrderedQueryable Find2([FromODataUri] string text,
[FromODataUri] string orderBy)
{
if (orderBy == null || orderBy.Length == 0)
orderBy = "CreatedOn DESC";
if (text == null || text.Length == 0)
return Get().OrderBy(orderBy);
var r = LikeToRegular(text);
return _db.People
.AsNoTracking() // can't use if using lazy loading
.Select(p => new
{
p.FirstName,
p.LastName,
p.Nickname,
p.CreatedOn,
p.CurrentWork.Title,
p.CurrentWork.Company.CompanyName
})
// Forces local computation, so pulls entire people dataset :-(
.Where(x => Regex.IsMatch(x.LastName ?? "", r)
|| Regex.IsMatch(x.FirstName ?? "", r, RegexOptions.IgnoreCase)
|| Regex.IsMatch(x.Nickname ?? "", r, RegexOptions.IgnoreCase)
|| Regex.IsMatch($"{x.FirstName} {x.LastName}", r,
RegexOptions.IgnoreCase))
.OrderBy(orderBy);
}
// Allow some wildcards in the search...
public static String LikeToRegular(String value)
{
return "^" + Regex.Escape(value)
.Replace("_", ".")
.Replace("%", ".*") + "$";
}