【发布时间】:2017-10-02 14:06:09
【问题描述】:
我正在研究一种使用 linq 到实体的简单文本搜索方法,我想在几个看起来像这样的地方重用它:
IQueryable<MyObject> query = db.MyObjects.Where(o => /* some criteria */);
query = query
.Select(o => new
{
value = o,
search = o.Foo + " " + o.Bar.X + " " + o.Bar.Y
})
.Where(o => o.search.contains("foo"))
.Select(o => o.value);
query = query.Where(o => /* some other criteria */);
我希望能够将 Select > Where > Select 序列转换为一个扩展方法,该方法可以给定一个 Func 将 search 属性拉在一起,如下所示:
public static IQueryable<T> Search<T>(this IQueryable<T> query, Func<T, string> selector, string phrase)
{
return query
.Select(o => new
{
value = o,
search = selector.Invoke(o)
})
.Where(o => o.search.Contains(phrase))
.Select(o => o.value);
}
然后可以这样使用:
query.Search(o => o.Foo + " " + o.Bar.X + " " + o.Bar.Y, "foo");
我认为这很简洁,它编译得很愉快,但它不会运行,因为 Linq to entity 不知道如何处理 Func 的 .Invoke() 方法。我还有其他一些 SO 问题,我可能应该使用 Expressiong<Func<T,string>> 而不仅仅是 Func,但我发现使这项工作起作用的唯一方法是用表达式替换 Select 语句的整个主体,然后要求表达式返回具有 value 和 search 属性的对象。
有没有办法使用Func 或Expression 只在匿名对象中创建搜索属性的值?
【问题讨论】:
-
正在转换为 IEnumerable
一个选项并使用 linq 到对象。 -
可悲的是,这会将所有内容都拉入内存,理想情况下我想使用数据库来完成这项艰苦的工作,因此需要通过实体框架将其转换为 SQL。
-
不需要两个选择,您可以只用一个
Where编写该查询,如o => (o.Foo + " " + o.Bar.X + " " + o.Bar.Y).Contains("foo")。鉴于该查询编写起来非常简单,我也认为不需要扩展方法来帮助您编写它。 -
@Servy 上面的代码说明了我正在尝试做的事情,而不是生产代码。我希望能够根据我正在查询的实体类型向它抛出不同的
Funcs。此外,在我的真实代码中,.Where(o => o.search.Contains(phrase))将扩展为使用多个搜索词,并根据它们的匹配程度对结果进行排名。以上只是一个简化的例子来说明手头的问题。
标签: c# entity-framework linq linq-to-entities