Before I post the full answer I'd like to give a shout out to Kristian Bortnik who came up with something very close to what I am going to provide. He had the best answer of anyone. In fact the main reason I am posting my answer is because I had had a slight difference that would potentially help with performance. For starters I added some class level variables and initialized them on class construction...so something like this:
private DataClassInfo _tableADataClassInfo = DataClassInfoProvider.GetDataClassInfo(tableAInfo.OBJECT_TYPE);
private DataClassInfo _tableBDataClassInfo = DataClassInfoProvider.GetDataClassInfo(tableBItem.CLASS_NAME);
You will notice that table b is done a little different and that is because it is a Custom Table. I wanted to make sure and include that so someone looking at this would be able to see it both ways. This particular solution requires you to get the class generated for a custom table and include it in you project. If you wish not to do that you can also create a constant in your solution that is the code name of the custom table and that can be used to get the DataClassInfo.
Once you have this you then do your where clause like this:
TableAInfoProvider.GetTableARecords()
.Source(sourceItem => sourceItem.Join<tableBItem>("tableBKey", "tableAKey"))
.WhereLessOrEquals(string.Format("{0}.TableBColumn", _tableBDataClassInfo.ClassTableName), value)
.Or().WhereLessOrEquals(string.Format("{0}.TableAColumn", _tableADataClassInfo.ClassTableName), value)
.ToList();
With this type set up you do not have to get the data class info every time the query is run for the same instance of the class and you now are taking advantage of the object for the table name. This means one less thing you have to change your code for to match the configuration of your Kentico system. That may not be a big deal to some people...but I think it is nice.