2009-11-20 3 views
0

Я не могу понять, как определить объект, используемый в моем запросе группировки LINQ, чтобы они могли быть строго типом.Строгий ввод запроса LINQ с использованием нескольких ключей сложных объектов

Я построил запрос группировки, который использует два сложных объекта в качестве ключей. Запрос работает, но я хотел бы иметь возможность объявить тип возвращаемого объекта.

У меня есть сложный тип ...

Public Class Student 
    Public Name As IndividualsName 
    Public EnrolledSchool As School 
    Public BirthHospital As BirthPlace 
    Public Grade As Integer 

    Public Sub New(ByVal name As IndividualsName, ByVal enrolledSchool As School, ByVal birthHospital As BirthPlace, ByVal grade As Integer) 
     Me.Name = name 
     Me.EnrolledSchool = enrolledSchool 
     Me.BirthHospital = birthHospital 
     Me.Grade = grade 
    End Sub 

End Class 

Public Class School 
    Inherits Location 


    Public Sub New(ByVal name As String, ByVal city As String, ByVal state As String) 
     MyBase.New(name, city, state) 
    End Sub 

    Public Shared Function GetMyHS() As School 
     Return New School("My High School", "My City", "My State") 
    End Function 
    Public Shared Function GetYourHS() As School 
     Return New School("Your High School", "Your City", "Your State") 
    End Function 
    Public Shared Function GetMyElementry() As School 
     Return New School("My Elementary", "My City", "My State") 
    End Function 
    Public Shared Function GetMyMiddleSchool() As School 
     Return New School("My Middle School", "My City", "My State") 
    End Function 

End Class 

Public Class IndividualsName 
    Public First As String 
    Public Last As String 

    Public Sub New(ByVal first As String, ByVal last As String) 
     Me.First = first 
     Me.Last = last 
    End Sub 

    Public Overrides Function ToString() As String 
     Return First & " " & Last 
    End Function 
End Class 

Public Class BirthPlace 
    Inherits Location 

    Public Sub New(ByVal name As String, ByVal city As String, ByVal state As String) 
     MyBase.New(name, city, state) 
    End Sub 

    Public Shared Function GetMyHospital() As BirthPlace 
     Return New BirthPlace("My General Hospital", "My City", "My State") 
    End Function 

    Public Shared Function GetYourHospital() As BirthPlace 
     Return New BirthPlace("Your General Hospital", "Your City", "Your State") 
    End Function 
End Class 

Public Class Location 
    Public Name As String 
    Public City As String 
    Public State As String 

    Public Sub New(ByVal name As String, ByVal city As String, ByVal state As String) 
     Me.Name = name 
     Me.City = city 
     Me.State = state 
    End Sub 

    Public Overrides Function Equals(ByVal obj As Object) As Boolean 
     Return Me.GetHashCode = obj.GetHashCode 
    End Function 

    Public Overrides Function GetHashCode() As Integer 
     Dim returnValue As Integer 
     returnValue = Me.Name.GetHashCode() Xor Me.City.GetHashCode() Xor Me.State.GetHashCode() 
     Return returnValue 
    End Function 

End Class 

То, что я собираю в списке и группировка вместе на основе двух сложных ключей.

Sub Main() 

    Dim students As List(Of Student) = New List(Of Student) 

    students.Add(New Student(New IndividualsName("Bill", "Jones"), School.GetMyHS(), BirthPlace.GetMyHospital(), 9)) 
    students.Add(New Student(New IndividualsName("George", "Jamesen"), School.GetMyHS(), BirthPlace.GetMyHospital(), 11)) 
    students.Add(New Student(New IndividualsName("Chris", "McCartney"), School.GetYourHS(), BirthPlace.GetMyHospital(), 9)) 
    students.Add(New Student(New IndividualsName("Sara", "Smith"), School.GetMyMiddleSchool(), BirthPlace.GetMyHospital(), 7)) 
    students.Add(New Student(New IndividualsName("Josh", "Jefferies"), School.GetMyMiddleSchool(), BirthPlace.GetYourHospital(), 8)) 
    students.Add(New Student(New IndividualsName("Mel", "Tompson"), School.GetMyHS(), BirthPlace.GetMyHospital(), 12)) 
    students.Add(New Student(New IndividualsName("Jill", "Schmidt"), School.GetYourHS(), BirthPlace.GetMyHospital(), 10)) 
    students.Add(New Student(New IndividualsName("Beth", "Taylor"), School.GetMyElementry(), BirthPlace.GetMyHospital(), 5)) 
    students.Add(New Student(New IndividualsName("Mark", "Thatcher"), School.GetMyElementry(), BirthPlace.GetMyHospital(), 4)) 
    students.Add(New Student(New IndividualsName("Tom", "Jones"), School.GetMyHS(), BirthPlace.GetYourHospital(), 9)) 
    students.Add(New Student(New IndividualsName("Kevin", "Woo"), School.GetMyMiddleSchool(), BirthPlace.GetYourHospital(), 7)) 

    Dim groupedQuery 'As IEnumerable(Of IGrouping()) 
    groupedQuery = From student In students _ 
        Group student By student.EnrolledSchool, student.BirthHospital Into Group _ 
       Select EnrolledSchool, BirthHospital, StudentGroup = Group 

    For Each groupItem In groupedQuery 
     Console.WriteLine(String.Format("School: {0}, Birth Place: {1}", groupItem.EnrolledSchool.Name, groupItem.BirthHospital.Name)) 
     'Console.WriteLine(String.Format("Group Item is type {0}.", groupItem.GetType())) 

     For Each item As Student In groupItem.StudentGroup 
      Console.WriteLine(String.Format("Name: {0} - Grade: {1}", item.Name.ToString(), item.Grade.ToString())) 
     Next 

    Next 
End Sub 

Все работает, но меня беспокоит, что когда я обрабатываю сбор данных, все объявляется анонимно. Это особенно назойливый объект, который создает сгруппированный список, находится в одной сборке, и он потребляется в веб-службе и на веб-сайте.

Я бы очень хотел, чтобы у вас был сильный тип возвращаемого IEnumberable, но я не могу понять, как объявить мой IGrouping interface.

я должен быть в состоянии пробежать свою структуру данных, как ...

Dim groupedQuery As IEnumerable(Of IGrouping(Of IDoNotKnowHowToDeclareMyComplexKey, Student)) 
    groupedQuery = From student In students _ 
        Group student By student.EnrolledSchool, student.BirthHospital Into Group _ 
       Select EnrolledSchool, BirthHospital, StudentGroup = Group 

    For Each groupItem As IGrouping(Of IDoNotKnowHowToDeclareMyComplexKey, Student) In groupedQuery 
     Console.WriteLine(String.Format("School: {0}, Birth Place: {1}", groupItem.Key.Name) 
     For Each item As Student In groupItem 
      Console.WriteLine(String.Format("Name: {0} - Grade: {1}", item.Name.ToString(), item.Grade.ToString())) 
     Next 

    Next 

, но я до сих пор не удалось выяснить, как объявить мой тип IGrouping.

ответ

2

Как сказал Брайан, создать новый класс:

Public Class SomeName 
    Public EnrolledSchool As School 
    Public BirthHospital As BirthPlace 
    Public StudentGroup As IEnumerable(Of Student) 
End Class 

Затем используйте его при группировке:

Dim result As IEnumerable(Of SomeName) 
result = (From student In students _ 
Group student By student.EnrolledSchool, student.BirthHospital Into Group _ 
Select New SomeName With {.EnrolledSchool = EnrolledSchool, .BirthHospital = BirthHospital, .StudentGroup = Group}) 

Если у вас есть какие-либо проблемы, место здесь код и ошибок вы получите.

+0

Отлично. Это именно то, что я искал. –

1

По определению, если что-то анонимно, вы не можете назвать его именем.

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

+0

Я попытался создать новый класс, который будет использоваться в качестве ключа для группировки, но я не мог заставить группировки отображать этот тип. Я продолжал получать ошибки преобразования типов. –