【问题标题】:Match Characters in LINQ QueryLINQ 查询中的匹配字符
【发布时间】:2011-11-22 19:51:51
【问题描述】:

我正在尝试匹配 LINQ 查询中邮政编码的前 5 个字符,并且我正在使用 SubString 来执行此操作。首先,我正在检查其中一个值是否为 NULL,因此它不会被炸掉。这是我正在使用的代码,但出现错误:

var lQuery = (from a in gServiceContext.CreateQuery("account")
    let AccountName = !a.Contains("name") ? string.Empty : a["name"]
    let Zip = !a.Contains("address1_postalcode") ? string.Empty : a["address1_postalcode"]
    let State = !a.Contains("address1_stateorprovince") ? string.Empty : a["address1_stateorprovince"]
    let Address = !a.Contains("address1_line1") ? string.Empty : a["address1_line1"]
    let City = !a.Contains("address1_city") ? string.Empty : a["address1_city"]
       where String.IsNullOrEmpty(Zip.ToString()) || String.IsNullOrEmpty(lLead.ZipCode) ? false : Zip.ToString().Substring(0,5).Equals(lLead.ZipCode.Substring(0,5))
       select new
       {
          Name = AccountName
       });
int c = lQuery.ToList().Count();

我得到的错误是:

“方法 'Where' 不能跟随方法 'Select' 或不受支持。请尝试根据支持的方法编写查询,或在调用不受支持的方法之前调用 'AsEnumerable' 或 'ToList' 方法。”

关于如何解决这个问题的任何想法或更好的方法的建议?

谢谢!

【问题讨论】:

    标签: c# asp.net linq linq-to-sql c#-4.0


    【解决方案1】:

    因此 Linq to Entities 不支持某些方法,因此您需要将它们放入内存并在那里执行操作:

    var lQuery = (from a in gServiceContext.CreateQuery("account")
        let AccountName = !a.Contains("name") ? string.Empty : a["name"]
        let Zip = !a.Contains("address1_postalcode") ? string.Empty : a["address1_postalcode"]
        let State = !a.Contains("address1_stateorprovince") ? string.Empty : a["address1_stateorprovince"]
        let Address = !a.Contains("address1_line1") ? string.Empty : a["address1_line1"]
        let City = !a.Contains("address1_city") ? string.Empty : a["address1_city"]
        select new 
        {
            AccountName, 
            Zip, 
            State, 
            Address, 
            City, 
            a.lLead
        }).AsEnumerable()
        .Where(i => String.IsNullOrEmpty(i.Zip.ToString()) || String.IsNullOrEmpty(i.lLead.ZipCode) ? false : i.Zip.ToString().Substring(0,5).Equals(i.lLead.ZipCode.Substring(0,5))
        .Select(i => new
        {
            Name = i.AccountName
        });
    

    生成的 SQL 看起来像这个过度简化的版本:

        Select name... as AccountName, address1_city as City, etc
        From account
    

    因此,如果您注意到没有 where 子句,则返回表帐户中的所有行。


    一些过滤
    var lQuery = (from a in gServiceContext.CreateQuery("account")
        let AccountName = !a.Contains("name") ? string.Empty : a["name"]
        let Zip = !a.Contains("address1_postalcode") ? string.Empty : a["address1_postalcode"]
        let State = !a.Contains("address1_stateorprovince") ? string.Empty : a["address1_stateorprovince"]
        let Address = !a.Contains("address1_line1") ? string.Empty : a["address1_line1"]
        let City = !a.Contains("address1_city") ? string.Empty : a["address1_city"]
        where Zip != null 
              && Zip != string.Empty 
              && lLead.ZipCode != null 
              && lLead.ZipCode != string.Empty 
              && Zip.Contains(lLead.ZipCode)
        select new 
        {
            AccountName, 
            Zip, 
            State, 
            Address, 
            City, 
            a.lLead
        }).AsEnumerable()
        .Where(i => i.Zip.ToString().Substring(0,5).Equals(i.lLead.ZipCode.Substring(0,5))
        .Select(i => new
        {
            Name = i.AccountName
        });
    

    【讨论】:

    • 值得注意的是,这不会在服务器上进行任何过滤,而是将所有数据带入内存。
    • 谢谢!我在帐户表中有超过 10,000 个帐户。是否有可能使它不会拉下整个桌子?
    • 试试我的更新,它应该过滤到一个非常小的子集
    • 您不能使用SqlMethods.Like 完全在服务器上进行过滤吗?
    • 谢谢!我尝试了第二个版本并得到“方法'Where'不能遵循方法'Select'或不受支持。尝试根据支持的方法编写查询或在调用不支持之前调用'AsEnumerable'或'ToList'方法方法。”有什么想法吗?
    【解决方案2】:

    您可以简化一些逻辑。这适用于我将您的结果集模拟为IEnumerable<Dictionary<string,string>>,所以我猜它会在不知道从 gServiceContext.CreateQuery() 返回什么类型的情况下处理您的数据:

    var lQuery = (from a in gServiceContext.CreateQuery("account")
                    let AccountName = a.Contains("name") ? a["name"] : String.Empty
                    let Zip = a.Contains("address1_postalcode") ? a["address1_postalcode"] : String.Empty
                    where  Zip.Substring(0, 5).Equals(lLead.ZipCode.Substring(0, 5))
                    select new
                                {
                                    Name = AccountName
                                });
    

    您也可以直接在 lQuery 上调用 .Count()。这让 LINQ 实现选择最有效的方法来计算结果,而不是将整个结果集加载到内存中并使用 LINQ to Objects 访问从 .ToList() 返回的列表的 .Count 属性。

    int c = lQuery.Count();
    

    【讨论】:

    • 如果 Zip 为 NULL 会发生什么,它不会轰炸子字符串吗?
    猜你喜欢
    • 1970-01-01
    • 2017-10-08
    • 1970-01-01
    • 1970-01-01
    • 2021-12-17
    • 1970-01-01
    • 2011-06-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多