Introduction

So yesterday I did [a post about Simple.Data][1] and Eli did [a post about Petapoco][2] based on what I did. And Eli commented that I did not have a primary key in my table.

In this post I will add that primary key and another table.

Adding a column

Adding a column should never be a big problem. But with Simple.Data it’s just no pain what so ever. Most ORM’s will require you to add a property to your model and then something to the mapping file. With Simple.Data the column is just available.

If I change the create table function to this.

Private Sub CreateTablePerson()
        Using cn = New SqlCeConnection(ConnectionString)
            If cn.State = ConnectionState.Closed Then
                cn.Open()
            End If
            Dim sql = "create table Person (Id int IDENTITY(1,1) PRIMARY KEY, LastName nvarchar (40) not null, FirstName nvarchar (40))"
            Using cmd = New SqlCeCommand(sql, cn)
                cmd.ExecuteNonQuery()
            End Using
        End Using
    End Sub```
I can now simply change my code to read the Id.

```vbnet
Sub Main()
        CreateDatabase()
        CreateTablePerson()
        Dim db = Simple.Data.Database.OpenConnection(ConnectionString)
        db.Person.Insert(New With {.LastName = "lastname1", .FirstName = "firstname1"})
        db.Person.Insert(New With {.LastName = "lastname1", .FirstName = "firstname2"})
        Dim result = db.Persons.FindAllByLastName("lastname1")
        For Each person In result
            Console.WriteLine("{0} {1} {2}", person.Id, person.LastName, person.FirstName)
        Next
        Dim count = db.Persons.FindAllByLastName("lastname1").Count
        Console.WriteLine("Count: " & count)
        Console.ReadLine()
    End Sub```
So adding a column is not a problem.

## Adding a table

So lets change our Person table a bit and add an address table.

```vbnet
Private Sub CreateTablePerson()
        Using cn = New SqlCeConnection(ConnectionString)
            If cn.State = ConnectionState.Closed Then
                cn.Open()
            End If
            Dim sql = "create table Person (Id int IDENTITY(1,1) PRIMARY KEY, LastName nvarchar (40) not null, FirstName nvarchar (40), AddressId int not null)"
            Using cmd = New SqlCeCommand(sql, cn)
                cmd.ExecuteNonQuery()
            End Using
        End Using
    End Sub

    Private Sub CreateTableAddress()
        Using cn = New SqlCeConnection(ConnectionString)
            If cn.State = ConnectionState.Closed Then
                cn.Open()
            End If
            Dim sql = "create table Address (Id int IDENTITY(1,1) PRIMARY KEY, Street nvarchar (40) not null, HouseNumber nvarchar (10))"
            Using cmd = New SqlCeCommand(sql, cn)
                cmd.ExecuteNonQuery()
            End Using
        End Using
    End Sub```
And now I can change my main method to this.

```vbnet
Sub Main()
        CreateDatabase()
        CreateTableAddress()
        CreateTablePerson()
        Dim db = Simple.Data.Database.OpenConnection(ConnectionString)
        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})
        Dim result = db.Persons.FindAllByLastName("lastname1")
        For Each person In result
            Console.WriteLine("Person: {0} {1} {2}", person.Id, person.LastName, person.FirstName)
            Dim address = db.Address.FindById(person.AddressId)
            Console.WriteLine("Address: {0} {1}", address.Street, address.HouseNumber)
        Next
        Dim count = db.Persons.FindAllByLastName("lastname1").Count
        Console.WriteLine("Count: " & count)
        Console.ReadLine()
    End Sub```
in the above I am doing it all wrong of course since I am creating a query to the address table for each of the rows in the persons. I think they call that a select N+1. I could and should do all this with one query.

And I can, kinda. But there is a catch.

First I will show you what works in C#

```csharp
var result = db.Persons.Query()
                .Join(db.Address).On(db.Persons.AddressId == db.Address.Id)
                .Select(db.Persons.LastName, db.Persons.FirstName, db.Address.Street, db.Address.HouseNumber);
            foreach(var person in result)
            {
                Console.WriteLine("Person: {0} {1}", person.LastName, person.FirstName);
                Console.WriteLine("Address: {0} {1}", person.Street, person.HouseNumber);
            }```
And that gives this SQL

```tsql
select [Person].[LastName],[Person].[FirstName],[Address].[Street],[Address].[HouseNumber] from [Person] JOIN [Address] ON ([Person].[AddressId] = [Address].[Id])```
So no more Select N+1. Oh joy.

Now we try the same thing in VB.Net.

```vbnet
Dim result = db.Persons.Query _
                .Join(db.Address).On(db.Persons.AddressId = db.Address.Id) _
                .Select(db.Persons.LastName, db.Persons.FirstName, db.Address.Street, db.Address.HouseNumber)
        For Each person In result
            Console.WriteLine("Person: {0} {1}", person.LastName, person.FirstName)
            Console.WriteLine("Address: {0} {1}", person.Street, person.HouseNumber)
        Next```
And grumble, grumble, curse, curse, swearword, swearword. It doesn’t work. It should, but it doesn’t. No really it doesn’t.

You get this errormessage.

> Public member ‘Address’ on type ‘Database’ not found.

But I swear it should work. 

So an hour or so later and trying other things. I get an idea.

```vbnet
Dim address = db.Address
        Dim result = db.Persons.Query _
                .Join(address).On(db.Persons.AddressId = address.Id) _
                .Select(db.Persons.LastName, db.Persons.FirstName, address.Street, address.HouseNumber)
        For Each person In result
            Console.WriteLine("Person: {0} {1}", person.LastName, person.FirstName)
            Console.WriteLine("Address: {0} {1}", person.Street, person.HouseNumber)
        Next```
And all of a sudden it works. I have yet to find a reason why the VB compiler doesn’t like it but I will look into it further when I have some time.

## Conclusion

You can add column easily and you can do joins quite easily. VB.Net however doesn’t seem to like it directly but there is a work around.

 [1]: /index.php/DesktopDev/MSTech/simple-data-and-vb-net
 [2]: /index.php/DesktopDev/MSTech/CSharp/playing-with-petapoco