Login or Sign Up to become a member!
LessThanDot Sit Logo

LessThanDot

Desktop Developer

Less Than Dot is a community of passionate IT professionals and enthusiasts dedicated to sharing technical knowledge, experience, and assistance. Inside you will find reference materials, interesting technical discussions, and expert tips and commentary. Once you register for an account you will have immediate access to the forums and all past articles and commentaries.

LTD Social Sitings

Lessthandot twitter Lessthandot Linkedin Lessthandot friendfeed Lessthandot facebook Lessthandot rss

Note: Watch for social icons on posts by your favorite authors to follow their postings on these and other social sites.

Your profile

    Search

    XML Feeds

    Google Ads

    « PetaPoco: Mapping related objectsSimple.Data and complex types: many to many »
    comments

    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.

    1. Public Class Person
    2.         Public Property LastName As String
    3.         Public Property FirstName As String
    4.         Public Property Address As Address
    5.         Public Property BadHabits As IList(Of BadHabit)
    6.     End Class
    7.  
    8.     Public Class Address
    9.         Public Property Street As String
    10.         Public Property HouseNumber As String
    11.     End Class
    12.  
    13.     Public Class BadHabit
    14.         Public Property BadHabit As String
    15.     End Class

    one to many

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

    1. Private Sub CreateTableBadHabits()
    2.         Using cn = New SqlCeConnection(ConnectionString)
    3.             If cn.State = ConnectionState.Closed Then
    4.                 cn.Open()
    5.             End If
    6.             Dim sql = "create table BadHabit (Id int IDENTITY(1,1) PRIMARY KEY, BadHabit nvarchar (40) not null, PersonId int)"
    7.             Using cmd = New SqlCeCommand(sql, cn)
    8.                 cmd.ExecuteNonQuery()
    9.             End Using
    10.             sql = "ALTER TABLE BadHabit ADD CONSTRAINT FK_BadHabit_Person FOREIGN KEY (PersonId) REFERENCES Person(Id)"
    11.             Using cmd = New SqlCeCommand(sql, cn)
    12.                 cmd.ExecuteNonQuery()
    13.             End Using
    14.         End Using
    15.     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.

    1. db.Address.Insert(New With {.Street = "street1", .HouseNumber = "1"})
    2.         db.Person.Insert(New With {.LastName = "lastname1", .FirstName = "firstname1", .AddressId = 1})
    3.         db.Person.Insert(New With {.LastName = "lastname1", .FirstName = "firstname2", .AddressId = 1})
    4.         db.BadHabit.Insert(New With {.BadHabit = "Drinks", .PersonId = 1})
    5.         db.BadHabit.Insert(New With {.BadHabit = "Smokes", .PersonId = 1})
    6.         db.BadHabit.Insert(New With {.BadHabit = "Eats to much", .PersonId = 2})

    And now for the querying.

    1. Dim result = db.Persons.FindAllByLastName("lastname1").WithAddress
    2.         For Each person In result
    3.             Console.WriteLine("{0} {1} {2} {3} {4}", person.Id, person.LastName, person.FirstName, person.Address.Street, person.Address.HouseNumber)
    4.             For Each badHabit In person.BadHabits
    5.                 Console.WriteLine(badHabit.BadHabit)
    6.             Next
    7.         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.

    1. Simple.Data.Ado:
    2. Text
    3. 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] from [Person] LEFT JOIN [Address] ON ([Address].[Id] = [Person].[AddressId]) WHERE [Person].[LastName] = @p1
    4. @p1 (String) = lastname1
    5.  
    6. Simple.Data.Ado:
    7. Text
    8. select [BadHabit].[Id],[BadHabit].[BadHabit],[BadHabit].[PersonId] from [BadHabit] WHERE [BadHabit].[PersonId] = @p1
    9. @p1 (Int32) = 1
    10.  
    11. Simple.Data.Ado:
    12. Text
    13. select [BadHabit].[Id],[BadHabit].[BadHabit],[BadHabit].[PersonId] from [BadHabit] WHERE [BadHabit].[PersonId] = @p1
    14. @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.

    1. Dim result = db.Persons.FindAllByLastName("lastname1").WithAddress.WithBadHabits
    2.         For Each person In result
    3.             Console.WriteLine("{0} {1} {2} {3} {4}", person.Id, person.LastName, person.FirstName, person.Address.Street, person.Address.HouseNumber)
    4.             For Each BadHabit In person.BadHabits
    5.                 Console.WriteLine(BadHabit.BadHabit)
    6.             Next
    7.         Next

    And now I get this sql instead.

    1. Simple.Data.Ado:
    2. Text
    3. 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
    4. @p1 (String) = lastname1

    And that's a lot better.

    You can however not do this.

    1. 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.

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

    Conclusion

    What can I say. It's simple.

    About the Author

    User bio imageChris is awesome.
    Social SitingsTwitterHomePageLTD RSS Feed
    InstapaperVote on HN

    No feedback yet

    Leave a comment


    Your email address will not be revealed on this site.

    To mislead the spambots.

    Your URL will be displayed.
    (Line breaks become <br />)
    (Name, email & website)
    (Allow users to contact you through a message form (your email will not be revealed.)