using System.Collections.Generic;
public static void Main()
var products = new List<Product>{
new Product{Id=1,Name="A"},
new Product{Id=2,Name="B"},
new Product{Id=3,Name="C"},
var compatibilities = new List<Compatible>{
new Compatible{Id=1,Prod1_id=1,Prod2_id=2},
new Compatible{Id=2,Prod1_id=1,Prod2_id=3},
new Compatible{Id=3,Prod1_id=3,Prod2_id=1},
new Compatible{Id=4,Prod1_id=1,Prod2_id=1},
List<long> addedProducts = new List<long>();
var p1_comps = GetAllCompatibles(compatibilities,1,1,addedProducts);
addedProducts = new List<long>();
var p2_comps = GetAllCompatibles(compatibilities,2,2,addedProducts);
addedProducts = new List<long>();
var p3_comps = GetAllCompatibles(compatibilities,3,3,addedProducts);
static List<long> GetCompatibles(IEnumerable<Compatible> table, long productId, long originalId, List<long> addedProducts)
(c.Prod1_id == productId &&
c.Prod2_id != originalId &&
!addedProducts.Contains(c.Prod2_id))
).Select(c => c.Prod2_id).ToList();
static List<long> GetAllCompatibles(List<Compatible> table,long pid, long origid, List<long> addedProducts)
List<long> result = new List<long>();
var Childs = GetCompatibles(table, pid, origid, addedProducts);
Childs.AddRange(GetCompatibles(table.Select(t =>
new Compatible { Prod1_id = t.Prod2_id, Prod2_id = t.Prod1_id }
).ToList(), pid, origid, addedProducts));
addedProducts.AddRange(Childs);
foreach (long child in Childs)
var temp = GetAllCompatibles(table, child, origid, addedProducts);
result.AddRange(temp.Select(p =>
GetCompatibles(table, p, origid, addedProducts)
{ l1.AddRange(l2); return l1; })
return result.Distinct().ToList();