Search code examples
simple.data

Simple.Data join without where clause including any primary table columns


I am using Simple.Data and have been trying to find an example that will let me do a join with the only condition in the WHERE clause be from the joined table. All of the examples I have seen always have at least one column in the primary table included in the WHERE. Take for example the following data:

private void TestSetup()
{
    var adapter = new InMemoryAdapter();
    adapter.SetKeyColumn("Events", "Id");
    adapter.SetAutoIncrementColumn("Events", "Id");
    adapter.SetKeyColumn("Doors", "Id");
    adapter.SetAutoIncrementColumn("Doors", "Id");
    adapter.Join.Master("Events", "Id").Detail("Doors", "EventId");
    Database.UseMockAdapter(adapter);
    db.Events.Insert(Id: 1, Code: "CodeMash2013", Name: "CodeMash 2013");
    db.Events.Insert(Id: 2, Code: "SomewhereElse", Name: "Some Other Conf");
    db.Doors.Insert(Id: 1, Code: "F7E08AC9-5E75-417D-A7AA-60E88B5B99AD", EventID: 1);
    db.Doors.Insert(Id: 2, Code: "0631C802-2748-4C63-A6D9-CE8C803002EB", EventID: 1);
    db.Doors.Insert(Id: 3, Code: "281ED88F-677D-49B9-84FA-4FAE022BBC73", EventID: 1);
    db.Doors.Insert(Id: 4, Code: "9DF7E964-1ECE-42E3-8211-1F2BF7054A0D", EventID: 2);
    db.Doors.Insert(Id: 5, Code: "9418123D-312A-4E8C-8807-59F0A63F43B9", EventID: 2);
}

I am trying to figure out the syntax I need to use in Simple.Data to get something similar to this T-SQL:

SELECT d.Code FROM Doors AS d INNER JOIN Events AS e ON d.EventID = e.Id WHERE e.Code = @EventCode

The final result should be only the three Door rows for EventId 1 when I pass in an event code of "CodeMash2013". Thanks!


Solution

  • First, a general point: since you've got criteria against the joined Events table, the LEFT OUTER is redundant; only rows with matching Event Codes will be returned, which implies only those rows where the join from Doors to Events was successful.

    If you've got referential integrity set up in your database, with a foreign key relationship from Doors to Events, then Simple.Data can handle joins automatically. With that in mind, this code will work, both with the InMemoryAdapter and SQL Server:

    List<dynamic> actual = db.Doors.FindAll(db.Doors.Events.Code == "CodeMash2013")
                   .Select(db.Doors.Id, db.Events.Name)
                   .ToList();
    
    Assert.AreEqual(3, actual.Count);
    

    If you don't have referential integrity set up then you should, but if you can't for some reason, then the following will work with SQL Server, but will trigger a bug in the InMemoryAdapter that I've just fixed but haven't done a release for yet:

    dynamic eventAlias;
    List<dynamic> actual = db.Doors.All()
                  .Join(db.Events, out eventAlias)
                  .On(db.Doors.EventID == eventAlias.Id)
                  .Select(db.Doors.Id, db.Events.Name)
                  .Where(eventAlias.Code == eventCode)
                  .ToList();
    
    Assert.AreEqual(3, actual.Count);