NET问答: LINQ 中为啥不能将 StartsWith() 转成 Like('abc%') ?

咨询区

  • Techy

我有下面的一段 asp.net core LINQ 代码。


   List<UserSearchResult> results = await db.ApplicationUsers.Where(u => u.Name.StartsWith(name) && !u.Deleted && u.AppearInSearch)
                                    .OrderByDescending(u => u.Verified)
                                    .ThenBy(u => u.DateAdded) // Added to prevent duplication of results in different pages
                                    .Skip(page * recordsInPage)
                                    .Take(recordsInPage)
                                    .Select(u => new UserSearchResult()
                                    {
                                        Name = u.Name,
                                        Verified = u.Verified,
                                        PhotoURL = u.PhotoURL,
                                        UserID = u.Id,
                                        Subdomain = u.Subdomain
                                    }).ToListAsync();

我发现它把linq转成下面这样了。


SELECT [t].[Name], [t].[Verified], [t].[PhotoURL], [t].[Id], [t].[Subdomain]
FROM (
 SELECT [u0].*
 FROM [AspNetUsers] [u0]
 WHERE (([u0].[Name] LIKE @__name_0 + N'%'
    AND CHARINDEX(@__name_0, [u0].[Name]) = 1)
   OR @__name_0 = NULL)
  AND [u0].[Deleted] = 0
  AND [u0].[AppearInSearch] = 1
 ORDER BY [u0].[Verified] DESC, [u0].[DateAdded]
 OFFSET @__p_1 ROWS FETCH NEXT @__p_2 ROWS ONLY
) [t]

我很疑惑的是:为什么会多出下面这一段? 仅仅用一个 like 不就可以了吗?


(CHARINDEX(@__name_0, [u0].[Name]) = 1)) OR (@__name_0 = N''))

回答区

  • Ivan Stoev

EF Core 中的sql转换规则仍然还有很多不足之处,离完美还差的很远,关于 StartsWithEndsWithContains 这些方法的sql转换,在内部或者外部讨论中都被多次提起,比如:github:https://github.com/dotnet/efcore/issues/474 ,如果你想生成你想要的,当前有一个变通的方式,就是一部分 sql,一部分 linq ,参考下面的代码。


var results = await db.ApplicationUsers
    //.Where(u => u.Name.StartsWith(name) && !u.Deleted && u.AppearInSearch)
    .FromSql("select * from ApplicationUsers where Name like {0}", name + "%")
    .Where(!u.Deleted && u.AppearInSearch)
    .OrderByDescending(u => u.Verified)
    .ThenBy(u => u.DateAdded) // Added to prevent duplication of results in different pages
    .Skip(page * recordsInPage)
    .Take(recordsInPage)
    .Select(u => new UserSearchResult()
    {
        Name = u.Name,
        Verified = u.Verified,
        PhotoURL = u.PhotoURL,
        UserID = u.Id,
        Subdomain = u.Subdomain
     }).ToListAsync();

上面的代码,我就用了 FromSql 做了这样的定制化。

  • R.Titov

Entity Framework 提供了一个类sql 的 EF.Functions.Like 几个方法,你可以把它拼在 Linq Expressions 中,比如下面的例子。


var likeExpression = name+"%";
... await db.ApplicationUsers.Where(u => EF.Functions.Like(u.Name,likeExpression)...

点评区

特斯拉最大的毛病就是太便宜,Entity Framework 最大的毛病就是封装的太狠,sql复杂起来后,原来便捷的sql生成就是此时最大的障碍!????

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值