Introduction

In my previous post I described how to deal with complex types and many to one dependencies now I will do the one to many relationships.

For this I will add a collection to our Person.

```vbnet Public Class Person Public Property LastName As String Public Property FirstName As String Public Property Address As Address Public Property BadHabits As IList(Of BadHabit) End Class

Public Class Address
    Public Property Street As String
    Public Property HouseNumber As String
End Class

Public Class BadHabit
    Public Property BadHabit As String
End Class```

one to many

For this we first have to add a table to our database.

vbnet Private Sub CreateTableBadHabits() Using cn = New SqlCeConnection(ConnectionString) If cn.State = ConnectionState.Closed Then cn.Open() End If Dim sql = "create table BadHabit (Id int IDENTITY(1,1) PRIMARY KEY, BadHabit nvarchar (40) not null, PersonId int)" Using cmd = New SqlCeCommand(sql, cn) cmd.ExecuteNonQuery() End Using sql = "ALTER TABLE BadHabit ADD CONSTRAINT FK_BadHabit_Person FOREIGN KEY (PersonId) REFERENCES Person(Id)" Using cmd = New SqlCeCommand(sql, cn) cmd.ExecuteNonQuery() End Using End Using End Sub We will better normalize it later when we have some time ;-). As you can see I also added the foreign key. I will leave the index creation up to you.

And we also need some more testdata.

vbnet db.Address.Insert(New With {.Street = "street1", .HouseNumber = "1"}) db.Person.Insert(New With {.LastName = "lastname1", .FirstName = "firstname1", .AddressId = 1}) db.Person.Insert(New With {.LastName = "lastname1", .FirstName = "firstname2", .AddressId = 1}) db.BadHabit.Insert(New With {.BadHabit = "Drinks", .PersonId = 1}) db.BadHabit.Insert(New With {.BadHabit = "Smokes", .PersonId = 1}) db.BadHabit.Insert(New With {.BadHabit = "Eats to much", .PersonId = 2}) And now for the querying.

vbnet Dim result = db.Persons.FindAllByLastName("lastname1").WithAddress For Each person In result Console.WriteLine("{0} {1} {2} {3} {4}", person.Id, person.LastName, person.FirstName, person.Address.Street, person.Address.HouseNumber) For Each badHabit In person.BadHabits Console.WriteLine(badHabit.BadHabit) Next Next Dude, that’s simple… I guess that’s why they call it Simple.Data and not PetaPoco 😉

Of course the above still lazy loads and gives this SQL.

```tsql Simple.Data.Ado: Text select [Person].[Id],[Person].[LastName],[Person].[FirstName],[Person].[AddressId],[Address].[Id] AS [with1AddressId],[Address].[Street] AS [with1AddressStreet],[Address].[HouseNumber] AS [with1Address__HouseNumber] from [Person] LEFT JOIN [Address] ON ([Address].[Id] = [Person].[AddressId]) WHERE [Person].[LastName] = @p1 @p1 (String) = lastname1

Simple.Data.Ado: Text select [BadHabit].[Id],[BadHabit].[BadHabit],[BadHabit].[PersonId] from [BadHabit] WHERE [BadHabit].[PersonId] = @p1 @p1 (Int32) = 1

Simple.Data.Ado: Text select [BadHabit].[Id],[BadHabit].[BadHabit],[BadHabit].[PersonId] from [BadHabit] WHERE [BadHabit].[PersonId] = @p1 @p1 (Int32) = 2``` That again is not always a desired behaviour and in our case we just want to eagerly fetch our data. Which of course is stupidly simple to do just by adding the WithStatement like this.

vbnet Dim result = db.Persons.FindAllByLastName("lastname1").WithAddress.WithBadHabits For Each person In result Console.WriteLine("{0} {1} {2} {3} {4}", person.Id, person.LastName, person.FirstName, person.Address.Street, person.Address.HouseNumber) For Each BadHabit In person.BadHabits Console.WriteLine(BadHabit.BadHabit) Next Next And now I get this sql instead.

vbnet Simple.Data.Ado: Text select [Person].[Id],[Person].[LastName],[Person].[FirstName],[Person].[AddressId],[Address].[Id] AS [__with1__Address__Id],[Address].[Street] AS [__with1__Address__Street],[Address].[HouseNumber] AS [__with1__Address__HouseNumber],[BadHabit].[Id] AS [__withn__BadHabits__Id],[BadHabit].[BadHabit] AS [__withn__BadHabits__BadHabit],[BadHabit].[PersonId] AS [__withn__BadHabits__PersonId] from [Person] LEFT JOIN [Address] ON ([Address].[Id] = [Person].[AddressId]) LEFT JOIN [BadHabit] ON ([Person].[Id] = [BadHabit].[PersonId]) WHERE [Person].[LastName] = @p1 @p1 (String) = lastname1 And that’s a lot better.

You can however not do this.

vbnet person.BadHabits(0).BadHabit Because that will give you this error.

No default member found for type ‘SimpleQuery’.

I think that is because BadHabits is of type SimpleQuery and the default for SimpleQuery is an IEnumerator. But you can do this instead.

vbnet person.BadHabits.ToList()(0).BadHabit

Conclusion

What can I say. It’s simple.