简体   繁体   中英

LINQ Query find columns where string contains any letter

I'm trying to find all customer codes where the customer has a status of "A" and whose code does not contain any letter using LINQ query.

var activeCustomers = Customers.Where(x => x.Status == "A" && x.Code.Any(n => !char.IsLetter(n))).Select(x => x.Code);

When I run this query in LinqPad I get the following error:

在此输入图像描述

As commenters have stated, IsLetter() cannot be translated to SQL. However, you could do the following, which will first retrieve all items with Status "A" from the database, then will apply your criteria after retrieval:

var activeCustomers = Customers.Where(x => x.Status == "A").AsEnumerable().Where(x => x.Code.Any(n => !char.IsLetter(n))).Select(x => x.Code);

You'll have to determine if it's acceptable (from a performance perspective) to retrieve all customers with "A" and then process.

The AsEnumerable() transitions your LINQ query to working not with IQueryable (which works with SQL) but with IEnumerable , which is used for plain LINQ to objects.

You'll need to do this as a two part query. First, you could get all the users who's status is "A":

var activeCustomers = Customers.Where(x => x.Status == "A").ToList();

After you've got those in-memory, you can create an additional filter for char.IsDigit :

var codes = activeCustomers.Where(x => x.Code.Any(n => !char.IsLetter(n)))
                           .Select(x => x.Code)
                           .ToArray();

Since it is LINQ 2 SQL, there is no natural way to translate char.IsLetter to something SQL can understand. You can hydrate a query that retrieves your potential candidates and then apply an addition in-memory filter. This also solves the issue where LINQ 2 SQL has a preference for a string and you are dealing with chars

var activeCustomers = Customers.Where(x => x.Status == "A").ToList();     
var filteredCustomers = activeCustomers.Where(x => 
    x.Code.Any(n => !char.IsLetter(n))).Select(x => x.Code).ToList();

There are two performance hits here. First, you're retrieving all potential records, which isn't too desirable. Second, in your above code you were only interested in an enumerable collection of codes, which means our query is including far more data than we originally wanted.

You could tighten up the query by only returning back to columns necessary to apply your filtering:

var activeCustomers = Customers.Where(x => x.Status == "A")
    Select(x => new Customer{ Status = x.Status, Code = x.Code }).ToList(); 

You still return more sets than you need, but your query includes fewer columns.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM