Select Join ricorsiva in c# con Linq

imagesOggi ho avuto bisogno di creare un extension method per poter selezionare in modo ricorsivo i figli di figli di un item padre in una lista. 🙂

Ecco una soluzione pulita per fare gerarchica ricorsiva join in LINQ e C#. Ho avuto difficolta’ a trovare su internet un esempio, quindi ho deciso di scrivere un post con il mio approccio che fornisce metodi di estensione per IEnumerabe <T> per fare ricorsione:

Prima di tutto la mia struttura gerarchica:
Text | ID | Parent ID
A | 1 | –
B | 2 | –
C | 3 | 1
D | 4 | 1
E | 5 | 2

I dati sono rappresentati dall’oggetto

public class ObjectData
{
   public string Text { get; set; }
   public int Id { get; set; }
   public int ParentId { get; set; }
}

mentre i nodi gerarchici dal seguente oggetto:

public class NodeData
{
 public string Text { get; set; }
 public IEnumerable<NodeData> Children { get; set; }
}

Il nostro obiettivo e’ avere un oggetto gerarchico fatto in questo modo:
A –>
|_ C
|_ D
B —>
|_ E

Usando il mio metodo di estensione RecursiveJoin LINQ, è possibile trasformare i dati (rappresentati da ObjectData) in dati gerarchici (rappresentati da NodeData) come segue:

Prima di tutto creiamo i nostri dati:

ObjectData[] elements = new ObjectData[][]
{
   new ObjectData[]{Id = 1, Text = "A"},
   new ObjectData[]{Id = 2, Text = "B"},
   new ObjectData[]{Id = 3, ParentId = 1, Text = "C"},
   new ObjectData[]{Id = 4, ParentId = 1, Text = "D"},
   new ObjectData[]{Id = 5, ParentId = 2, Text = "E"}
};

E poi implementiamo il RecursiveJoin per creare il nostro oggetto “ricorsivo”

IEnumerable<NodeData> nodes = elements.RecursiveJoin(element => element.Id,
 element => element.ParentId,
 (ObjectData element, IEnumerable<NodeData> children) => new NodeData()
 {
 Text = element.Text,
 Children = children
 });

Ci saranno due root nodi A e B. A avra’ i figli C e D mentre B avra’ come figlio solo E.
L’esempio usa semplicemente la forma del metodo RecursiveJoin con la seguente firma:

public static IEnumerable<TResult> RecursiveJoin<TSource, TKey, TResult>
   (this IEnumerable<TSource> source,
      Func<TSource, TKey> parentKeySelector,
      Func<TSource, TKey> childKeySelector,
      Func<TSource, IEnumerable<TResult>, TResult> resultSelector);

Il codice della classe si puo’ trovare sul mio Github

Annunci

Il modo più veloce di usare Excel in Linq2Sql

Di seguito alcune righe di codice per utilizzare dati di Excel in Linq2Sql :


string filename = @"C:\myfile.xls";
string connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" +
"Data Source=" + filename + ";Extended Properties=Excel 8.0;";

OleDbDataAdapter dataAdapter = new OleDbDataAdapter("SELECT * FROM [Sheet1$]", strConn);
DataSet myDataSet = new DataSet();
dataAdapter.Fill(myDataSet, "ExcelInfo");
DataTable dataTable = myDataSet.Tables["ExcelInfo"];

var query = from r in dataTable.AsEnumerable()
select new
{
RelationNr = r.Field<double>("RelationNumber"),
ClientName = r.Field<string>("ClientName"),
};

foreach (var item in query)
{
Console.WriteLine(item.ClientName);
}