0

I have this query

from d in db.v_Report_CompanySearches
where d.PersonName.ToLower().Contains(mPersonName)
orderby d.PersonName ascending
group d by d.PersonName into g
select (g);

But it returns all columns, when I just want PersonName. Plus I want to make sure PersonName is distinct, right now it returns duplicate values.

What is wrong here?

omega
  • 40,311
  • 81
  • 251
  • 474
  • Call 'Distinct()' method on your result. – Sham Oct 03 '18 at 20:46
  • 1
    Possible duplicate of [Is there way to use Distinct in LINQ query syntax?](https://stackoverflow.com/questions/5720945/is-there-way-to-use-distinct-in-linq-query-syntax) – Sam Arustamyan Oct 03 '18 at 21:07

4 Answers4

3

Call Dictinct at the end of query using parenthesis, you don't need the grouping thing there.

var result  = (from d in db.v_Report_CompanySearches
               where d.PersonName.ToLower().Contains(mPersonName)
               orderby d.PersonName ascending
               select d.PersonName ).Distinct();
JuanK
  • 2,056
  • 19
  • 32
-1

original question: Is there way to use Distinct in LINQ query syntax?

accepted answer:

The Distinct extension method in LINQ does not have a query syntax equivalent.

See http://blogs.msdn.com/b/charlie/archive/2006/11/19/linq-farm-group-and-distinct.aspx for additional information as to why.

answer #2

There is no Distinct() method syntax in the language integrated query syntax. The closest you could do would be to move the current call:

var q = (from c in tbl
         select c.TABLE_TYPE).Distinct();
Community
  • 1
  • 1
Isitar
  • 1,286
  • 12
  • 29
  • you voted down my answer i will kindly not vote down yours but will point out that Distinct() is looking at the class and calling a comparison on the class. The question only cares about the PersonName. What if the table was StackOverflowLogins with your Name and LoginDateTime and IP. Distinct on the class would return every login you did because the change in Date and maybe IP ... rather the asker wants unique persons who logged in. Am i making sense? – Juls Oct 04 '18 at 00:22
-1

Use g.First()

from d in db.v_Report_CompanySearches
where d.PersonName.ToLower().Contains(mPersonName)
orderby d.PersonName ascending
group d by d.PersonName into g
select (g.First().PersonName);
Juls
  • 658
  • 6
  • 15
  • 1
    First is not the same as distinct – Isitar Oct 03 '18 at 21:04
  • I added another answer explaining what First is and why Key is a better solution for his use case. – Isitar Oct 04 '18 at 07:28
  • You are going through great lengths to insist on being right. #1 - First() will not return an Enumerable. It will return the first item in the list of CompanySearch. – Juls Oct 04 '18 at 09:33
  • I'm sorry but my downvote is locked so i cannot remove it unless you edit your answer. if you use first outside the query, you're right but if you use first, like in your example inside the select (g.First()), it will select the first element of the group. groupby will result in an IEnumerable>, using First() on it will result in an IEnumerable if you use first outside the query (from ... select g).First() it will return the first IGrouping – Isitar Oct 04 '18 at 09:35
  • There is nothing new your teaching anyone. Everyone knows that .First() returns the first object in the group. Everyone knows that .First().PersonName will return the exact same list as Key. Your behaving like a bad Stackoverflow community member. You posted an answer that was incorrect (which is not a problem it happens all the time); then you down voted an answer that was correct just because you didn't understand it; now you have double-down on insisting your particular way is the only correct way. Stop trying to explain it's not helping. – Juls Oct 04 '18 at 15:26
  • I'm sorry if I have angered you, but your first answer was simply not what the original poster wanted. Your statement: > #1 - First() will not return an Enumerable is simply not correct. now that you have corrected your answer, i'll remove my downvote since it's a valid solution now. – Isitar Oct 04 '18 at 15:38
-1

Use select (g.key) to select the grouping key only.

from d in db.v_Report_CompanySearches
where d.PersonName.ToLower().Contains(mPersonName)
orderby d.PersonName ascending
group d by d.PersonName into g
select (g.Key);

in your case the result will be an Enumerable<string> assuming PersonName is a string.

If you use the g.First() method as proposed by another answer, the result will be an IEnumerable<CompanySearch> assuming db.v_Report_CompanySearches is a list of CompanySearch. The result will contain only distinctive values for the PersonName but the other fields are just filled with the first match.

If you just select(g) the result is an Enumerable<IGrouping<string, CompanySearch>> The result will contain the Personnames distinctive as a key (since you group by them) but contains all the results as values. (You can extract them by using a SelectMany statement, see How to get values from IGrouping).

Since my answer got downvoted I make another example, everyone can execute and check the validiy of it:

class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public override string ToString()
    {
        return $"{Name}: {Age}";
    }
}

static void Main(string[] args) {
    personList = new List<Person>()
    {
        new Person {Name = "Jay", Age = 25},
        new Person {Name = "Hans", Age = 25},
        new Person {Name = "Fritz", Age = 25},
        new Person {Name = "Hello", Age = 26},
        new Person {Name = "World", Age = 27},
        new Person {Name = "Whatever", Age = 26},
        new Person {Name = "ASDF", Age = 24},
        new Person {Name = "Foo", Age = 25},
        new Person {Name = "Bar", Age = 22},
    };
    var ages = from p in personList
               where p.Age > 22
               orderby p.Age ascending
               group p by p.Age into g
               select (g);

    Console.WriteLine($"select(g): {ages.GetType()}");

    var ages2 = from p in personList
        where p.Age > 22
        orderby p.Age ascending
        group p by p.Age into g
        select (g.First());

    Console.WriteLine($"select(g.First()): {ages2.GetType()}");

    var ages3 = ages.First();
    Console.WriteLine($"(select(g)).First(): {ages3.GetType()}");
}

In the output you can see that the first one is an IEnumerable<IGrouping<int,Person>>, the second output is an IEnumerable<Person> and the third one is an IGrouping<int,Person>.

Isitar
  • 1,286
  • 12
  • 29