0

can i do it in linq to find parent-child relationship dynamically ?

when user gives the child input,we have to find out the immediate parent and Top Level parent for the child.

Schema:

**LocationId**   **LocationName**  **ParentId**
 1               InterNational          0
 2                National              1
 3                Regional              2
 4                SubRegional           3
 5                Area                  4
 6                City                  5
 7                Town                  6
 8              Municipality            7



Input:When user type input as Area
Outpt:immediate parent: SubRegional
Top parent:International
total parent:4

if:town
immediate parent:City
top parent:international
total parent:6

class

     public class ParentChild
        {
            public int LocationId { get; set; }
            public string LocationName { get; set; }
            public int parentId { get; set; }

            public static List<ParentChild> LocationParent()
            {
                var s = new List<ParentChild>{
                new ParentChild {LocationId=1,LocationName="InterNational",parentId=0},
                new ParentChild {LocationId=2,LocationName=" National",parentId=1},
                new ParentChild {LocationId=3,LocationName=" Regional ",parentId=2},
                new ParentChild {LocationId=4,LocationName=" SubRegional",parentId=3},
                new ParentChild {LocationId=5,LocationName="Area ",parentId=4},
                new ParentChild {LocationId=6,LocationName=" City ",parentId=5},
                new ParentChild {LocationId=7,LocationName="Town ",parentId=6},
                new ParentChild {LocationId=8,LocationName="Municipality ",parentId=7}
                };

                return s;

            }

        }


        public class ParentChildViewModel()
        {
            public int LocationId { get; set; }
            public string LocationName { get; set; }
            public int parentId { get; set; }
            public string ParentName{get;set;}
            public int immediateparentId {get;set;}
            public string immediateparentName {get;set;}


        }

controller

   public ActionResult ParentChilds(string x)
        {

            var ss = from y in ParentChild.LocationParent()
                     where y.LocationName == x
                     select 
-- How to do this in linq logic here?how i have write the logic

            return View(ss);


        }

View:

@model IEnumerable <Dataclasses.ParentChildViewModel>


@{
    ViewBag.Title = "ParentChilds";
}

<h2>ParentChilds</h2>

@foreach (var x in Model)
{
   <p>currentLocationName: @x.LocationName</p>
    <p>currentLocationId :@x.LocationId</p>

    <p>LocationTopParentId :@x.parentId</p>
   <p>LocationTopParent:@x.ParentName</p>

<p>LocationimmediateparentId :@x.immediateparentId</p>
   <p>LocationimmediateparentName:@x.immediateparentName</p>
    <br />

}
3
  • 1
    you don't give any information on the internal data structures used -- you just show the data model. please give these details if you expect a usable result. Commented Nov 13, 2015 at 19:53
  • That's not even a model, just a table schema. Commented Nov 13, 2015 at 20:14
  • I would recommend changing your parentId of International to null instead of 0. Then set up a self-referencing foreign key constraint on the table (ParentId must point to a valid id in the same table), and then update your data context. You should then have a property called Parent on your ParentChild class, in which you can use to reference the direct parent. Commented Nov 13, 2015 at 21:26

2 Answers 2

2

Something reusable might look like this

public static class MyExtensions
    {
        public static List<T> Parents<T>(this List<T> list, T current, Func<T, int> getId, Func<T, int> getPid)
        {
            List<T> returnlist = new List<T>();

            T temp = list.FirstOrDefault(x => getPid(current) == getId(x));
            while (temp != null)
            {
                returnlist.Add(temp);
                current = temp;
                temp = list.FirstOrDefault(x => getPid(current) == getId(x));
            }

            return returnlist;
        }
    }

and for your specific case it would them be used as

var locations = ParentChild.LocationParent();
            var parents = locations.Parents(locations[6], x => x.LocationId, x => x.parentId);
            Console.WriteLine( "Immediate Parent {0}, top - parent:{1}, count : {2}",
            parents.First().LocationName,
            parents.Last().LocationName,
            parents.Count );
Sign up to request clarification or add additional context in comments.

1 Comment

This is cute -- very linqy to create a list of the path to the top. It could also be implemented without an extension using Aggregate
0

I'd use linq to put the data in a dictionary, then it is a simple search and lookup.

void Main()
{

  List<loc> basedata = new List<loc>() 
  {
     new loc() { ID = 1, name = "InterNational", pID = 0 },
     new loc() { ID = 2, name = "National", pID = 1 },
     new loc() { ID = 3, name = "Regional", pID = 2 },
     new loc() { ID = 4, name = "SubRegional", pID = 3 },
     new loc() { ID = 5, name = "Area", pID = 4 },
     new loc() { ID = 6, name = "City", pID = 5 },
     new loc() { ID = 7, name = "Town", pID = 6 },
     new loc() { ID = 8, name = "Municipality", pID = 7 },
  };

  Dictionary<int,loc> data = basedata.ToDictionary(x => x.ID);

  string test1 = "Area";

  loc test1parent = data[data.First(x => x.Value.name == test1).Value.pID];
  loc top1;
  for(top1 = data.First(x => x.Value.name == test1).Value;top1.pID!=0;top1 = data[top1.pID]);

  Console.WriteLine("Immediate Parent = "+test1parent.name);
  Console.WriteLine("Top parent = "+top1.name);

  string test2 = "Town";

  loc test2parent = data[data.First(x => x.Value.name == test2).Value.pID];
  loc top2;
  for(top2 = data.First(x => x.Value.name == test2).Value;top2.pID!=0;top2 = data[top2.pID]);

  Console.WriteLine("Immediate Parent = "+test2parent.name);
  Console.WriteLine("Top parent = "+top2.name);

}


public class loc
{
   public int ID { get; set; }
   public string name { get; set; }
   public int pID { get; set; }
}

2 Comments

I've deleted my answer, but this is essentially the same answer I had 10 minutes earlier but building your own lookups instead of letting LINQ do it automatically. I realized that the OP couldn't have used LINQs automatic generation of virtual properties because his table is setup odd. He uses 0 to denote no parent instead of null, which means he can't possibly have referential integrity set up correctly on the table (no record exists with an id of 0), and I don't believe LINQ would allow you to set up a navigation property either for the same reason(s).
@RobertMcKee - yes I agree - there are other strange things about his example code, having a list inside of the ParentChild class makes no sense to me (given the other properties). I wrote my answer to be self contained which might prove helpful.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.