简体   繁体   中英

Linq-to-SQL WHERE IN statement returns more than is wanted

Okay I am trying to make a partial view and controller whose job it is to select and display a list of accessories for whatever product is currently being viewed in the parent view.

The database I am working again stores this information in a field that is formatted as a comma separated list, like this:

productnr,productnr2,productnr3,productnr4

So I use the following code to retrieve this list and use it to run the equivalent of an SQL WHERE IN statement:

[ChildActionOnly]
public ActionResult _ListAccessories(string Artnr)
{
    var List = (
        from ArtTbl in db.ArtTbl
        where ArtTbl.ArticleNr == Artnr
        select ArtTbl.AccessoryList)
        .SingleOrDefault();

    var AccList = customFunctions.Accessories(text);

    var AccQuery = 
        from Art in db.ArtTbl
        where AccList.Contains(ArtTbl.ArticleNr)
        select new AccessoryList
        {
            Artnr = ArtTbl.ArticleNr,
            Name = ArtTbl.Namefield_1,
        };

    return PartialView(AccQuery);
}

The function in the AccList variable transforms the first string into the result below. I did this because all the examples I saw used such a syntax, the function seems to work properly as I've tested by sending it as a viewBag to the view just to check that it looks correct:

"productnr", "productnr2", "productnr3", "productnr4"

This is what the AccessoryList model looks like as well, just a very simple model:

public class AccessoryList 
{
    public string Artnr { get; set; }
    public string Name { get; set; }

    public AccessoryList()
    {
    }
}

Now this code works, but the problem is that it is too generous, if I have a product number in the list that says "AP500W" then it will also return "AP500" or just "500". This is a problem as it should only return the exact match.

The reason you're having problems begins and ends with this:

The database I am working again stores this information in a field that is formatted as a comma separated list

LINQ is translating this to a SQL statement that is treating the entire field value as a single entity - because it is a single entity. When Contains() is evaluated, it's simply looking for matching substring values. That's why AP500 and 500 match AP500W .

Since you're really trying to do the equivalent of WHERE IN (...) you'll need to convert your MVA (multi-valued attribute) into a set of distinct values.

The query works in your example where you send a view bag of individual string values :

"productnr", "productnr2", "productnr3", "productnr4"

Your database value is actually a single string value :

"productnr, productnr2, productnr3, productnr4"

The difference is subtle but very important. Notice in the second example there is only one string of data that acts as a single value.

Dennis,

I know the following wont exactly answer your problem. However, it may bring you closer to a resolution. In your example, you are saying:

where AccList.Contains(ArtTbl.ArticleNr)

this is why you are getting wildcard results across the resultset. One way to mitigate this would be to only examine the front portion of the result string:

where AccList.StartsWith(ArtTbl.ArticleNr)

you could even have a look at (tho i'm certain this won't work):

where AccList.Any(x => x.StartsWith(ArtTbl.ArticleNr))

in the above case, you'd get results for 'AP50', 'AP500' etc, etc. May be worth further investigation (i'm not at a compiler right now, so can't validate if the above works as expected or not :-)).

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