简体   繁体   中英

Join Records in Linq one column?

在此输入图像描述

I want the output like

Test Genre1/
Test Genre2/
Test Genre3/Test genre1               //(Bcoz id 1 as Test Genre1)
Test Genre4/Test genre2               //(Bcoz id 2 as Test Genre2)
Test genre1/Test Test genre3/Genre5   //(Bcoz id 3 as Test Genre3)

It should be combination of the id and parent id in Linq .

Any help will be appreciated...

You can try a recursive method returning IEnumerable defined on the entity class:

public class Genre
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int? ParentId { get; set; }

    public IEnumerable<Genre> GetSelfAndAncestors(IEnumerable<Genre> items)
    {
        yield return this;

        if (ParentId.HasValue)
        {
            var parent = items.First(x => x.Id == ParentId.Value);

            foreach (var ancestor in parent.GetSelfAndAncestors(items))
            {
                yield return ancestor;
            }
        }
    }
}

Usage:

var genres = new[]
{
    new Genre {Id = 1, Name = "Test Genre 1", ParentId = null},
    new Genre {Id = 2, Name = "Test Genre 2", ParentId = null},
    new Genre {Id = 3, Name = "Test Genre 3", ParentId = 1},
    new Genre {Id = 4, Name = "Test Genre 4", ParentId = 2},
    new Genre {Id = 5, Name = "Test Genre 5", ParentId = 3}
};

foreach (var genre in genres)
{
    var path = genre.GetSelfAndAncestors(genres);
    Console.WriteLine(String.Join("/", path.Select(x => x.Name)));
}

If the tree is deep, you might notice a significant performance hit comparing this implementation with a non- IEnumerable one.

Given a method to be called recursively which

  1. Adds the name to a string
  2. Calls itself recursively with any existing parent

private static string SelectGenreName(IEnumerable<Genre> all, Genre g)
{
    var s = g.Name + '/';
    if(g.ParentId.HasValue){
        s += SelectGenreName(all, all.Single(x => x.Id == g.ParentId.Value));   
    }
    return s;
}

The code to get a sensible result* is quite straightforward:
* sensible result; Your last example was reversed from the previous 4. The above gives results as per your first four examples. ie Child/Parent/Grandparent

var genres = new[]
{
    new Genre {Id = 1, Name = "Test Genre 1", ParentId = null},
    new Genre {Id = 2, Name = "Test Genre 2", ParentId = null},
    new Genre {Id = 3, Name = "Test Genre 3", ParentId = 1},
    new Genre {Id = 4, Name = "Test Genre 4", ParentId = 2},
    new Genre {Id = 5, Name = "Test Genre 5", ParentId = 3}
};

var result = genres.Select(g => SelectGenreName(genres,g));

foreach(var r in result)
    Console.WriteLine(r);

Live example: http://rextester.com/MXQUH43732

Create a recursive function and use that function in your linq. something like this.

//Recursive method
 private static string GetParentPath( IEnumerable<Item> items , Item item )
    {
        if (item.ParentId.HasValue)
        {
            return GetParentPath(items, items.First(i => i.Id == item.ParentId)) + "/" + item.GenreName;
        }

        return item.GenreName;
    }



var items = new Item[]
        {
            new Item {Id = 1, GenreName = "Test Genre 1", ParentId = null},
            new Item {Id = 2, GenreName = "Test Genre 2", ParentId = null},
            new Item {Id = 3, GenreName = "Test Genre 3", ParentId = 1},
            new Item {Id = 4, GenreName = "Test Genre 4", ParentId = 2},
            new Item {Id = 5, GenreName = "Test Genre 5", ParentId = 3}
        };



 // Linq query
        var result = from child in items
                  select new { Path = GetParentPath(items, child) };



    //Class used in example
 public class Item
    {
        public int Id { get; set; }

        public string GenreName { get; set; }

        public int? ParentId { get; set; }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM