Code first node tree implementation with many parents nodes - c#

I'm trying to implement tree view using code first to save it in db. Entity class is
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public int? ParentId { get; set; }
[ForeignKey("ParentId")]
public virtual ICollection<Category> Parents { get; set; }
}
But when I try to use the class, it looks like EF saves a Child, not a Parent.
For example, I've created a parent node 'Category1' and then a child node 'Category2' (and added 'Category1' to Parents collection)
entity.Parents.Add(new Category(){...});
But instead of the expected behavior "Category2_child_for_Category1", I see "Category1_child_for_Category2"
And if I try to save a couple of parents, db saves only the last value from the list as a child, not a parent.
Can anybody explain how to fix it?
Many thanks

Related

Get all children of same object by Entity Framework

I need your help. I have next simple class:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public int ParentId { get; set; }
public IEnumerable<Person> People { get; set; }
}
I need to get class by ID and all children of the class that have ParentId same with ID of first class (and children of children)? I need to use LINQ filtration. Thanks for help!
Okay, there are two solutions that I could find. The first is using the recursive method on the server-side. But in this variant, you need each time request database for each level of hierarchy. The best solution is using Recursion in SQL. You need to do only one request to the database. I attach the link. https://medium.com/swlh/recursion-in-sql-explained-graphically-679f6a0f143b

ASP MVC 5 - Remove Child Entities From Parent

How can I remove All child entities from a one to many relationship via the parent - Note I only want to remove the children.
public class Parent
{
public int Id { get; set; }
public ICollection<Child> Children { get; set; }
}
public class Child
{
public int Id { get; set; }
public int ParentId { get; set; }
public string Name { get; set; }
public virtual Parent Parent { get; set; }
}
Is there a shorthand way, lets say something like below:
parent.children.Remove();
I believe that your mechanism for deleting the child elements in EF 4 and above should be:
parent.children.ToList().ForEach(c => context.Children.Remove(c));
context.SaveChanges();
I have found in the past that it may be faster to write a DELETE yourself, but you should decide what is best for you. Introducing a SQL DELETE in an Entity Framework solution adds some complexity both to testing and because your DELETE will depend on things you may have been trying to avoid as EF takes care of it all. Always measure before you optimize and decide what trade-offs work for you.

Reference to objects lost afer adding a new item

I have a model that looks like this:
public class Parent
{
public string Name { get; set; }
public List<Child> Children { get; set; }
}
public class Child
{
public string Name { get; set; }
public Parent Parent { get; set; }
public Child ParentChild { get; set; }
public List<Child> Children { get; set; }
}
That means that I have a parent that can have children. The children can also have children. Each child has a reference to the parent it belongs to (even if it is a child of a child).
I have the following in my database:
Parent
Child_1
Child_1_1
Child_1_1_1
I now want to add Child_1_2.
var child = new Child(){ Name = "Child 1.2" };
child.ParentChild = child_1;
child.Parent = parent;
context.Children.Add(child);
context.SaveChanges();
My problem is now that this will change Child_1_1 and Child_1_1_1. The reference to their parent will be lost after this Code. They will be null in the database.
This has something to do with Entity Framework not loading all the references (especially not references that are nested).
Is there a way to do this and tell the Entity Framework to add the Parent but not change the parent or any of its children?
My guess is that you are not showing the exact model here. Your model would mean two different tables.
A quick fix would be to add parent.Children.Add(child).
Although I would severely recommend you to redo your model into something similar (although still doesn't make sense in a larger contex):
public class Person
{
public string Name { get; set; }
public List<Child> Children { get; set; }
}
public class Parent : Person
{
// Probably this class would contain something useful
}
public class Child : Person
{
public Person ParentPerson { get; set; }
}

Fluent NHibernate: Map property without foreign key?

I have these two classes:
public class Parent
{
public virtual string Name { get; set; }
public virtual string Family_id { get; set; }
}
public class Children
{
public virtual string Name { get; set; }
public virtual DateTime BirthDate { get; set; }
public virtual string Family_id { get; set; }
}
When I fetch a parent, I also want to fetch the oldest (ordered by BirthDate) children that has the same Family_id as the parent.
There is no foreign key between the parent and the children in the database.
(I do not want to use two different repositories, I want the functionality in the mappings)
Is property-ref something I can use?
One strategy would be to force an Eager Load on a Children collection and create another property to get the oldest child.
Property-Ref is used to join to another table using a column which is not the primary key.
public class Parent
{
public virtual int Id {get; set;}
public virtual string Name { get; set; }
public virtual string Family_id { get; set; }
public virtual Children OldestChild {
get {
return Children.OrderBy(x=>x.BirthDate).FirstOrDefault();
}}
public virtual IList<Children> Children {get; set;}
}
public class ParentMap : ClassMap<Parent>{
public ParentMap(){
Id(x=>x.Id);
Map(x=>x.Name);
HasMany(x=>x.Children).PropertyRef("Family_id").Fetch.Join();
}
}
Another possibility would be to add a column to the Parent table (OldestChild_FK) and then join in that row from the Children table.
I think what you want to do is create a property on the Parent called OldestChild or a list of Oldest Children and ignore that property and write some custom query (HQL or SQL) to return the results you want.
Here is a thread on ignoring properties in FluentNhibernate.

Retrieving Hierarchal data in Entity Code-First

I have some hierarchal data. The Model class I use looks like this:
public class Category
{
[Key]
public int CategoryID { get; set; }
[Required]
[StringLength(64)]
public string Name { get; set; }
public int? ParentCategoryID { get; set; }
[ForeignKey("ParentCategoryID")]
public Category ParentCategory { get; set; }
[Required]
public int ListOrder { get; set; }
// left/right
public int TreeLeft { get; set; }
public int TreeRight { get; set; }
} // eo class Category
I've used the techniques outlined here to store my data, and inserting and retrieving data is not a problem.
What I would like to do, is add a Category collection to this class:
public virtual IEnumerable<Category> {get; set; }
I've used this technique in the past (learned from the Mvc tutorials), to include related tables when getting data. However, when I tried this I received an error with regard to IEnumerable<> being abstract (which is understandable, I guess the framework couldn't figure out what I want to do)...
... and indeed, being new to LINQ, I have no idea what the LINQ would look like that would give me back a collection of Category instances each of which had their children inside them.
If it's not possible I guess I can construct the list manually, use a regular LINQ query to get all the categories at a particular position (and their children) and manually populate it all.
I was wondering if LINQ could do this for me?
Thanks in advance!
If you have a self reference fk than the collection should be generated automatically when you add the table to the dbml file
And will look something like this:
[global::System.Data.Linq.Mapping.AssociationAttribute(Name="Category_Category", Storage="Categories", ThisKey="pkCategoryID", OtherKey="ParentCategoryID")]
public EntitySet<Category> Categories
{
get
{
return this._Categories;
}
set
{
this._Categories.Assign(value);
}
}
Dont use IEnumerable<Category> but Collection<Category> . If that is your problem..

Categories