tags:

views:

102

answers:

2

I'm trying to get this LINQ to work but fails with the error.

Cannot convert lambda expression to type 'System.Collections.Generic.IEqualityComparer' because it is not a delegate type

Basically I have IEnumerable and I'm trying to group the data, as in:

string sql = @"SELECT [t0].[Contact_Account] AS [Contact], [t0].[Work_Phone] AS [WorkPhone], [t0].[SR_NUM] AS [SRNum] ";
sql += "FROM [Base_SR] AS [t0] ";
sql += "WHERE ([t0].[Country] = 'USA') AND (NOT ([t0].[Work_Phone] LIKE '+%')) ";
sql += "AND ([t0].[Product] = 'SP3D') AND (DATEPART(Year, [t0].[DateOpened]) = {0})";

sql = String.Format(sql, curYear);

var sqlCmd  = new SqlCommand(sql, new SqlConnection(connectionString));
var adapter = new SqlDataAdapter(sqlCmd);
var dataSet = new DataSet();
adapter.Fill(dataSet);
var siebelRows = dataSet.Tables[0].AsEnumerable();

return siebelRows.GroupBy(sr => new { AreaCode = sr.Field<string>("WorkPhone").Substring(0, 3), 
          Contact = sr.Field<string>("Contact") },
     (key, lst) => new Customer 
     {
                        Id = Guid.NewGuid(),
      AreaCode = key.AreaCode,
      CustAccount = key.Contact,
      FirstPhoneNo = lst.First().Field<string>("WorkPhone").Substring(0, 10),
      FirstSRNum= lst.First().Field<string>("SRNum"),
      SRCount = lst.Count()
     })
     .Take(5);

Any thoughts ?

DigEmAll's suggestion helped (thanks) and I had to do this:

public class GroupKey
{
    public string AreaCode { get; set; }
    public string Contact { get; set; }
}

And then change the LINQ to this GroupBy key:

GroupBy<DataRow, GroupKey, IEnumerable<Customer>>

return siebelRows.GroupBy<DataRow, GroupKey, IEnumerable<Customer>>(sr => new GroupKey
{
    Contact = sr.Field<string>("Contact"),
    AreaCode = sr.Field<string>("WorkPhone").Substring(0, 3)
},
    (key, lst) => new Customer
        {
            Id = Guid.NewGuid(),
            AreaCode = key.AreaCode,
            CustAccount = key.Contact,
            FirstPhoneNo = lst.First().Field<string>("WorkPhone").Substring(0, 10),
            FirstSRNum = lst.First().Field<string>("SRNum"),
            SRCount = lst.Count()
        }).OrderByDescending(c => c.SRCount)
        .Take(5);

Don't like creating a concrete type for the key...any way around this ??

thanks Sunit

+1  A: 

You mixed your GroupBy and Select. Try the following as a work-around (looking into the overload you're using):

return siebelRows.GroupBy(sr => new
                          { 
                              AreaCode = sr.Field("AreaCode")
                                           .Substring(0, 3),
                              Contact = sr.Field("Contact")
                          })
                 .Select(kvp => new Customer
                                {
                                    Id = Guid.NewGuid(),
                                    AreaCode = kvp.Key.AreaCode,
                                    CustAccount = kvp.Key.Contact,
                                    // rest of the assignment
                                }
                 .Take(5);
Justin Niessner
Your solution should return the expected result, but actually I think the OP is trying to use [this GroupBy overload](http://msdn.microsoft.com/en-us/library/bb549393.aspx), so he's not really "mixing" anything... I can't see why the original code doesn't compile
Thomas Levesque
I'm using the overload for GroupBy public static IEnumerable<IGrouping<K, E>> GroupBy<T, K, E>( this IEnumerable<T> source, Func<T, K> keySelector, Func<T, E> elementSelector);
Sunit
Thomas beat me to the explanation (:
Sunit
@Sunit, in that case your code doesn't match the method signature... the only one that seems to match is the one I linked to.
Thomas Levesque
+2  A: 

I think your problem is in the Field<T> in your Anonymous type definition.

You should specify the type T (cannot be inferred from the usage), then compiler will recognize the correct GroupBy overload.


EDIT according to OP changes:

You don't need to create a concrete type, just specify explicitly the right T in Field<T>(...), so in your code:

sr => new { AreaCode = sr.Field<string>("WorkPhone").Substring(0, 3), 
            Contact = sr.Field<string>("Contact") }

EDIT 2:

OK, I've edited your question because actually your <...> were hidden (don't use <code><pre> manually, just click on the appropriate button ;-) ).

Anyway, your last code has an error in the GroupBy types specification:

is not <DataRow, GroupKey, IEnumerable<Customer>>,

but <DataRow, GroupKey, Customer>

because you just have to specify the inner Type of the returned IEnumerable.

Then, I've tried your last code, and also removing the concrete type GroupKey (and obviously removing the GroupBy types specification) it is perfectly valid:

var customers = siebelRows.GroupBy( 
    sr => new 
    {
        Contact = sr.Field<string>("Contact"),
        AreaCode = sr.Field<string>("WorkPhone").Substring(0, 3)
    },
    (key, lst) => new Customer
    {
        Id = Guid.NewGuid(),
        AreaCode = key.AreaCode,
        CustAccount = key.Contact,
        FirstPhoneNo = lst.First().Field<string>("WorkPhone").Substring(0, 10),
        FirstSRNum = lst.First().Field<string>("SRNum"),
        SRCount = lst.Count()
    })
    .OrderByDescending(c => c.SRCount)
    .Take(5);
return customers;
digEmAll
Good point, I missed that... But in that case the compiler is not showing the actual cause of the error
Thomas Levesque
Or perhaps the OP didn't notice it ? I don't know I'm guessing...
digEmAll
@Sunit: check my edit ;)
digEmAll
I think StackOverflow stripped the '<' out since it's there already. So that makes it puzzling...looks like the issue is with the incorrect signature I was using. It should be this one public static IEnumerable<TResult> GroupBy<TSource, TKey, TResult>( this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, IEnumerable<TSource>, TResult> resultSelector)
Sunit
Since I'm returning IEnumerable<Customer> from the actual method.
Sunit
@Sunit: edited, sorry for the late reply
digEmAll
Thanks..I changed it so that I get the latest SR->DateOpened .Select (x =>new {Contact=x.Contact_Account, SiteId=x.SiteID, DateOpened=x.DateOpened, WorkPhone=x.Work_Phone, SRNum=x.SR_NUM} ) .AsEnumerable() .GroupBy (sr => sr.SiteId, (siteid,lst)=> new {SiteId=siteid, SRCount= lst.Count(), SR = lst.First (l =>l.DateOpened == lst.Max (l => l.DateOpened))}) but now it again complains of IEqualityComparer ??
Sunit
Mmh, maybe the problem is that you're using `l` (lowercase L) for 2 nested lambda expression : `[...]First(l =>l.DateOpened == lst.Max (l => l.DateOpened))`. Try to change the second with another variable name. Anyway, this GroupBy overload seems very sensible, and it gives wrong compiler error informations.
digEmAll