На самом деле есть способ сделать это, при условии, что отношения между вашими таблицами 1: 1 (хотя пропущенные строки не являются большой проблемой): создайте два отношения вместо одного, т.е.
var joinColT1 = table1.Columns["ID"];
var joinColT2 = table2.Columns["FK_IDT1"];
var rel1 = new DataRelation("R1To2", joinColT1, joinColT2, false);
var rel2 = new DataRelation("R2To1", joinColT2, joinColT1, false);
theDataSet.Relations.Add(rel1);
theDataSet.Relations.Add(rel2);
// Add the column you're after
var hisFriend = new DataColumn("HisFriend", typeof(string), "Parent([R2To1]).[HisFriend]");
table1.Columns.Add(hisFriend);
// Add a back-reference to the other table against the friend if you want, too
var hisFriendsSalary = new DataColumn("HisFriendsSalary", typeof(decimal) "Parent([R1To2]).[Salary]");
table2.Columns.Add(hisFriendsSalary);
Однако пара замечаний: во-первых, когда я впервые экспериментировал с этим, я получил синтаксические ошибки без квадратных скобок вокруг имен отношений в выражении. Возможно, это было связано с именами, которые я использовал для отношений.
Во-вторых, я полагаю, что результат выражений хранится в строках (они не вычисляются «вовремя» при доступе, они вычисляются при изменении значений и сохраняются). Это означает, что вы сохраняете данные дважды, используя этот подход. Иногда это хорошо, а иногда нет.
В-третьих, вы заметите, что я не использую ограничения. Это потому, что в моих типичных сценариях использования я не ожидаю, что в каждой строке будет аналог в другой таблице (поэтому, во-первых, довольно часто встречаются две таблицы!). Это может (я не проверял dotnetframework.org) влиять на производительность.