Rick D
Rick D

Reputation: 139

LINQ query is not returning expected results

Can anyone help with this, I'm trying to perform a simple query using LINQ and I am not getting the expected results.

private void ButtonProductSearch_Click(object sender, EventArgs e)
{
    string userSearch = textBoxSearchText.Text.ToLower();

    var productSearch =
        from product in sales
        where product.ToString().ToLower() == userSearch
        select product;

    MessageBox.Show(productSearch.Count().ToString()); //For Testing

    sales.Clear();
    sales.AddRange(productSearch);
    DisplaySales(sales);
}

The message, which is just for testing is returning 0, I have ensured that I am entering a relevant search string.

sales is a Sale object, which is populated from a csv file, and there is a dataGridView which is populated from the Sale object, screenshot below. When th application is run, sales reads every line from the csv, and datagridview populates with that data, screenshot below

screenshot

Upvotes: 0

Views: 185

Answers (2)

Oliver
Oliver

Reputation: 45109

I think the answer from @dotNET seems for me to be the correct answer. Just for completeness I build up an example and also implemented case insensitive search:

using System;
using System.Linq;
using Bogus;

public class Program
{
    public static void Main()
    {
        var productsFactory = new Faker<Product>()
            .StrictMode(true)
            .RuleFor(p => p.TransactionDate, f => f.Date.Between(DateTime.UtcNow.AddDays(-100), DateTime.UtcNow))
            .RuleFor(p => p.Category, f => f.Commerce.ProductAdjective())
            .RuleFor(p => p.Price, f => f.Random.Decimal(10, 100))
            .RuleFor(p => p.PaymentType, f => f.PickRandomWithout(PaymentType.Unknown))
            .RuleFor(p => p.Name, f => f.Commerce.ProductName())
            .RuleFor(p => p.City, f => f.Address.City())
            .RuleFor(p => p.State, f => f.Address.State())
            .RuleFor(p => p.Country, f => f.Address.Country());

        var products = productsFactory.Generate(50);
        var userSearch = products.Skip(3).First().Name.Substring(2, 3);
        var productSearch = products.Where(product => product.Name.IndexOf(userSearch, StringComparison.CurrentCultureIgnoreCase) >= 0);

        foreach (var result in productSearch)
        {
            Console.WriteLine(String.Format("{0:G} {1} {2:N2}", result.TransactionDate, result.Name, result.Price));
        }

        Console.ReadKey();
    }
}

public class Product
{
    public DateTime TransactionDate { get; set; }
    public string Category { get; set; }
    public decimal Price { get; set; }
    public PaymentType PaymentType { get; set; }
    public string Name { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Country { get; set; }

}

public enum PaymentType
{
    Unknown,
    Mastercard,
    Visa,
    Amex,
}

Upvotes: 0

dotNET
dotNET

Reputation: 35470

You need to understand that in the query from product in sales, product refers to a row of sales and not to the column named Product. Therefore doing ToString() on product will return that row's string representation (which is most often the name of the class itself). You should write your query like this:

var productSearch =
    from s in sales
    where s.Product.ToLower() == userSearch
    select product;

Here again, s refers to a row of sales and therefore has got all the properties like Product, Price and Payment Type etc. You can therefore ask LINQ to filter for rows that have their Product property equal to userSearch. Since Product is of type string, you don't even need to do ToString() on it.

Upvotes: 2

Related Questions