【问题标题】:Spliting string in LINQ and using 2nd Index value在 LINQ 中拆分字符串并使用第二个索引值
【发布时间】:2020-02-21 11:17:08
【问题描述】:

我坚持拆分电子邮件以获取 LINQ 的 group by 子句中的电子邮件域,以按域对数据进行分组。 我的 LINQ 是

(
    from u in DbContext.UserProfiles
    join ap in DbContext.AspNetUsers
        on u.PhoneNo equals ap.PhoneNumber
    where u.IsVerified == true
    let domainName = ap.Email.Split('@').Skip(1).FirstOrDefault()

    /*ap.Email.Split('@')[1]  
    ap.Email.Substring(ap.Email.IndexOf('@') + 1, ap.Email.Length) 
    ap.Email.Split('@').ElementAt(1) 
    GetDomainHost(ap.Email)*/

    group ap by new
    {
        DomainName = domainName 
    }
    into grp
    select new
    {
        grp.Key.DomainName,
        TotalUsers = grp.Count()
    };
)

注意:我也尝试过注释代码,但显示的异常与 LINQ not supported

我需要拆分电子邮件并获取将在第二个索引上的域。 我该如何解决这个问题?

编辑:

我面临转换的例外是

LINQ to Entities 无法识别方法 'System.String ElementAt[String](System.Collections.Generic.IEnumerable`1[System.String], int32)' 方法,并且这个方法不能翻译成store 表达。

其实我正在尝试转换这个SQL

select dbo.GetDomainFromEmail(ap.Email) as 'Domains', Count(*) as 'Total Users' 
from AspNetUsers ap 
join UserProfile up 
    on ap.PhoneNumber = up.PhoneNo and 
    up.IsVerified = 1 
group by dbo.GetDomainFromEmail(ap.Email)

到LINQ。 dbo.GetDomainFromEmail(ap.Email) 是一个函数,定义为 Substring(ap.Email, Charindex('@', ap.Email)+1, LEN(ap.Email)).

【问题讨论】:

  • 您应该向我们提供实际的完整错误消息,否则很难提供帮助。我猜问题出在实体框架上,它试图弄清楚如何处理您的查询。您唯一的解决方案是将数据具体化到本地的内存列表中,然后按该列表进行分组。
  • 您也可以查看thread 了解如何正确拆分电子邮件
  • @PavelAnikhouski 您给定的线程仅解释了拆分字符串,但我的问题是如何在LINQ 中执行此操作。因为LINQ 无法识别我所有拆分字符串的尝试。在我的问题中提供。

标签: c# sql arrays .net linq


【解决方案1】:

我建议使用正则表达式组。举个例子:

string emailAdress = "yourEmailHere@theDomain.net";

Regex pattern = new Regex("@(?<domain>[a-zA-Z0-9]*)");
Match match = pattern.Match(emailAdress);
string domain = match.Groups["domain"].Value;

【讨论】:

    【解决方案2】:

    您可能希望在使用 Split 之前先执行查询,因为 Linq to Entity 不支持 Split 方法。因此,您可以使用AsEnumerable 使选择发生在内存中而不是 EF 中。

    所以我们可以先获取所有域名:

    var emails = (from u in DbContext.UserProfiles
    join ap in DbContext.AspNetUsers
        on u.PhoneNo equals ap.PhoneNumber
    where u.IsVerified == true
    select new
    {
        Email = ap.Email
    }).Distinct().AsEnumerable();
    

    然后我们可以从emails获取所有域。

    更新:

    另外,如果你想避免将数据加载到内存中,那么你可以execute plain SQL query获取所有域:

    var results = db1New.Database.SqlQuery<string>("
        SELECT 
        SUBSTRING(up.Email, CHARINDEX('@', up.Email) + 1, LEN(up.Email) ) AS Domain
        FROM dbo.UserProfiles up 
        GROUP BY SUBSTRING(up.Email, CHARINDEX('@', up.Email) + 1, 
        LEN(up.Email))").ToArray();
    

    【讨论】:

    • 我不仅需要所有域,还需要每个域的计数。这就是为什么我必须在电子邮件域上应用聚合 group by。
    • @Fahad 我建议获取所有域,因为我知道 Linq To Entities 中没有 Split 函数。
    • 是的,LINQ To Entities 中没有拆分
    • @Fahad 所以你需要将数据存入内存然后使用Splitmethd
    • 但这需要很长时间才能将其放入ToList() 或AsEnumerable() 然后对其执行split()。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-22
    • 1970-01-01
    • 1970-01-01
    • 2021-05-31
    相关资源
    最近更新 更多