2009-04-12 3 views
1

Учитывая этот код:Linq к SQL: DISTINCT с анонимными типами

dgIPs.DataSource = 
    from act in Master.dc.Activities 
    where act.Session.UID == Master.u.ID 
    select new 
    { 
     Address = act.Session.IP.Address, 
     Domain = act.Session.IP.Domain, 
     FirstAccess = act.Session.IP.FirstAccess, 
     LastAccess = act.Session.IP.LastAccess, 
     IsSpider = act.Session.IP.isSpider, 
     NumberProblems = act.Session.IP.NumProblems, 
     NumberSessions = act.Session.IP.Sessions.Count() 
    }; 

Как вытащить Distinct() на основе только отдельного адреса? То есть, если я просто добавлю Distinct(), он оценит всю строку как отдельную и, следовательно, не найдет дубликатов. Я хочу вернуть ровно одну строку для каждого объекта act.Session.IP.

Я уже нашел this answer, но это похоже на другую ситуацию. Кроме того, Distinct() отлично работает, если я просто выбираю act.Session.IP, но у него есть столбец, который я хочу избежать, и я не хочу этого делать, привязывая вручную столбцы datagrid вручную.

ответ

3
dgIPs.DataSource = 
    from act in Master.dc.Activities 
    where act.Session.UID == Master.u.ID 
    group act by act.Session.IP.Address into g 
    let ip = g.First().Session.IP 
    select new 
    { 
     Address = ip.Address, 
     Domain = ip.Domain, 
     FirstAccess = ip.FirstAccess, 
     LastAccess = ip.LastAccess, 
     IsSpider = ip.isSpider, 
     NumberProblems = ip.NumProblems, 
     NumberSessions = ip.Sessions.Count() 
    }; 

Или:

dgIPs.DataSource = 
    from act in Master.dc.Activities 
    where act.Session.UID == Master.u.ID 
    group act.Session.IP by act.Session.IP.Address into g 
    let ip = g.First() 
    select new 
    { 
     Address = ip.Address, 
     Domain = ip.Domain, 
     FirstAccess = ip.FirstAccess, 
     LastAccess = ip.LastAccess, 
     IsSpider = ip.isSpider, 
     NumberProblems = ip.NumProblems, 
     NumberSessions = ip.Sessions.Count() 
    }; 
+1

Я пробовал этот подход, и при профилировании результат нашел, что он сгенерировал довольно красивый SQL – LaserJesus

+0

Brehtt, согласился. Кажется, что он всегда запрашивает db как минимум дважды. –

0

Одна из перегрузок Enumerable.Distinct принимает экземпляр IEqualityComparer. Просто напишите класс, который реализует IEqualityComparer и который сравнивает только два свойства Address.

К сожалению, вам нужно указать имя анонимного класса, который вы используете.

+1

Если я правильно помню, что перегрузка не поддерживается в LINQ к SQL (так как он не может передать IEqualityComparer на сервер), только в LINQ к объектам. Таким образом, плакат также должен был бы вызвать ToList() в результирующем наборе перед вызовом Distinct(). – itowlson