在动态Linq中使用"Single"的用法

3

我正在尝试将我在Linq中工作的查询转换为可以在动态Linq(使用System.Linq.Dynamic)中工作的查询,因为我希望用户能够形成自己的查询,并且这个查询字符串将在运行时添加到其他查询字符串上。

我有一个查询:

db.incidents.Where(a => a.incidentLocations.Single().location.street.Contains(location);

我尝试将其转换为以下动态linq字符串:

query = 
string.Concat("incidentLocations.Single().location.street.Contains(\"", location, "\")");

db.incidents.Where(query);

这里的location是包含搜索文本的字符串。

我已经成功将所有其他查询转换为动态linq,但这一个查询却出现了异常错误:

“不存在可用的聚合方法'Single'”

我知道动态linq不支持所有扩展方法,能否告诉我如何解决这个问题。


我从未使用过动态 Linq,但你尝试过 SingleOrDefault() 吗?它做的事情或多或少相同。唯一的区别是当找不到记录时它会返回 null 而不是抛出错误。 - Bazzz
我对动态 Linq 不是完全熟悉,但它是针对 SQL 还是对象的? - Davy8
也许应该把single改成First()? - Henrik
既然您可以将多个Linq查询组合成一个巨大的表达式,为什么要将硬编码部分转换为动态部分呢?保持它们原来的样子,然后只需添加额外的查询作为动态过滤器或子选择即可。 - Jason Coyne
2个回答

7
获取 Linq.Dynamic 的源代码,复制粘贴 Where 方法,更改方法内部的签名和字符串为函数名称,然后就可以使用了。我曾经这样做来添加 Single First 等功能,但由于我不在开发机器上,所以无法在此处复制。如果需要的话,稍后我会补充。

编辑:如果您决定使用它,这里是 Single 方法:

public static object Single(this IQueryable source)
    {
        if (source == null) throw new ArgumentNullException("source");
        return source.Provider.Execute(
            Expression.Call(
                typeof(Queryable), "Single",
                new Type[] { source.ElementType },
                source.Expression));
    }

感谢您的回答,我确实考虑过这样做,但我认为修改源代码会带来更多麻烦,不值得。最终,我改变了dbml映射关系(这些关系相当复杂),以避免使用single(),就像Manatherin所说的那样。 - CDrnly
虽然我无法验证您的答案是否有效,因为我已经用不同的方法解决了问题,并且项目已经部署!感谢您费心尝试解决我的问题。(很抱歉我没有足够的声望来点赞您。) - CDrnly
如果您添加了此方法,则还需要将Single添加到IEnumerableSignatures接口(在同一文件中)。 - ctsears

4
抱歉挖掘了一个很老的帖子,但我认为我可以添加一些有价值的信息!
我不得不在Linq to Entities中使用First() / FirstOrDefault()完成此操作,而非您的Linq to SQL,我可以确认@Guillaume86的解决方案确实可行!
这是我如何修改MicrosoftDynamic.sql: 我在静态DynamicQueryable类内添加了以下内容:
    public static object FirstOrDefault(this IQueryable source)
        {
            if (source == null) throw new ArgumentNullException("source");
            return source.Provider.Execute(
                Expression.Call(
                    typeof(Queryable), "FirstOrDefault ",
                    new Type[] { source.ElementType },
                    source.Expression));
        }

我还修改了接口IEnumerableSignatures,如下:

            void FirstOrDefault();

我使用FirstOrDefault是因为在linq to entities中,当它不是最后一个调用时,不支持First()。
您可以为任何受支持的函数重复此操作 :)

1
我很久以前问过这个问题,但现在我把它设置为答案。 - CDrnly

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接