Suppose that we have two classes as bellow:
class Parent
{
public int ParentId {get; set;}
}
class Child : Parent
{
public int ChildId {get; set;}
}
According to the above, which line is correct and why? and also which line is not correct and why?
Parent p = new Child();
Child c = new Parent();
Update: I forget to inherit Child from Parent and I correct it!
First one is correct, second is not.
By definition, a Child will inherit all properties and methods of a Parent; however, Parent will not have all properties and/or methods of a Child, so the second statement wouldn't make sense:
class Parent
{
public int ParentId { get; set; }
public void Eat { ... }
}
class Child : Parent
{
public int ChildId { get; set; }
public void Play { ... }
}
Parent child = new Child();
child.Eat(); // this makes sense since this is common functionality
Child parent = new Parent();
parent.Play() // this does not make sense since a Parent doesn't know hot to play
Related
I am currently working with efcore on an Blazor Server-Side-App and run into to following Problem.
Situation is like following:
I do have a Parent, Child and Family Class which are "connected" to eachother.
class Parent
{
public int ParentId { get; set; }
ICollection<Child> children {get;set;}
}
class Child
{
public int ChildId { get; set; }
public Parent ParentId { get; set; }
}
class Family
{
public int FamilyId { get; set; }
public ICollection<Parent> Parents {get;set;}
public ICollection<Child> Children {get;set;}
}
Now I do have a Dialog where you can create a new Parent and you can also add a Child to the Parent. The Family was already created in a View before.
My Code inside the Dialog for Parent and Child looks like this:
#code {
private Parent parent;
private Family Family;
ICollection<Family> families;
protected override async Task OnInitializedAsync()
{
using var context = DbFactory.CreateDbContext();
families = await context.families.ToListAsync();
Family = families.FirstOrDefault();
}
void CreateParent()
{
parent = new Parent();
parent.Family = Family;
}
void AddChildToParent()
{
Child child = new Child();
child.Family = Family;
parent.children.Add(child);
}
void Save()
{
using var context = DbFactory.CreateDbContext();
context.Parents.Update(parent);
context.SaveChanges();
}
}
When i try to save this, then EFcore throws an InvalidOperationException: The Instance of entity type "Family" cannot be tracked because another instance is already beeing tracked.
What am i doing wrong?
Btw. Code ist just pseudo
Are the instances of parent and Family in the private fields are coming from ef core and tracked?
If so, then no need to call Update on Save method, but just context.SaveChanges();
void Save()
{
using var context = DbFactory.CreateDbContext();
//context.Parents.Update(parent); omit this line
context.SaveChanges();
}
Otherwise, you can do the following:
void Save()
{
using var context = DbFactory.CreateDbContext();
context.Families.AsNoTracking.Update(Family);
context.SaveChanges();
}
I've a class with Tree hierarchy as below. I need to set Leaf node to status "InProgress". Then All ancestors needs to have change from NotStarted to InProgress. And if all leaf nodes were Complete, it immediate parent status need to be Complete. Is there a quick way to do it other than recursively iterating multiple times?
pubic class Node
{
public string Name { get; set; }
public List<Node> Children { get; set; } = new List<Node>();
public int NodeStatus {get; set;} // 1=>NotStarted (default); 2=> InProgress; 3=>Complete
}
One simple way can be that you make a different class for child notes and notify your parent class each time when its property is changed:
Parent
public class Node
{
public string Name { get; set; }
public List<Node> Children { get; set; } = new List<Node>();
private int _nodeStatus;
// 1=>NotStarted (default); 2=> InProgress; 3=>Complete
public virtual int NodeStatus
{
get => _nodeStatus;
set
{
_nodeStatus = value;
// If started, then change all children property to 'In progress'
if(value == 2)
Children.ForEach(child => child.NodeStatus = 2);
}
}
private int CountCompleted { get; set; }
public void NotifyChildChanged(int childStatus)
{
if (childStatus == 3)
{
CountCompleted++;
if(CountCompleted == Children.Count)
// Do your stuff
}
else
{
CountCompleted--;
}
}
}
Child
public class ChildNode : Node
{
private int _nodeStatus;
public override int NodeStatus
{
get => _nodeStatus;
set
{
_nodeStatus = value;
NotifyChildChanged(value);
}
}
}
Basically, what you will have is a separate implementation of NodeStatus for Parent and Child classes and inside of their implementation you just put other needed methods like changing childs' values or notifying parent about child's complete. In the parent's case, however, you should be careful, because every time you change the parent it will change all children, so you might want to have also some kind of private bool which will be checking whether the progress has already been started or not.
P.S for simplicity, I used just methods, however, you might want to implement it through delegates and events.
I'm re-asking this from a question a couple of days ago now I've whittled the problem down.
Two simple objects:
public class Parent
{
public int Id { get; set; }
public virtual Child Child { get; set; }
public string Name { get; set; }
}
public class Child
{
public int Id { get; set; }
public string Name { get; set; }
}
I find a Parent object using a DbContext method e.g.
Parent parentToUpdate = _context.Parent.Find(1);
This object comes equipped with a populated child already, say with Id 22, generated as a System.Data.Entity.DynamicProxy
I then have a new child object which becomes a null because it wasn't found in the database, using the same DbContext:
Child newChild = _context.Child.Find(999); // returns null
I then try to overwrite the parentToUpdate object's child with the newChild object:
parentToUpdate.Child = newChild;
I expect .Child to become null - This doesn't work unless I step through the code - The parentToUpdate.Child doesn't become null!
WHY? and How can I nullify my parentToUpdate.Child object? before I do _context.SaveChanges()
Ok so thanks to the breadcrumb of lazy loading I ended up circling back on Include which I'd glossed over earlier looking for a solution.
It's as simple as changing the Find in context statement from
Parent parentToUpdate = _context.Parent.Find(1);
To
Parent parentToUpdate = _context.Parent.Include(x => x.Child).Where(x => x.Id == 1);
I need to access base class properties which is a list from derieved class. Below is the example.I need this for unit testing.
class child : List<Parent>
{
//this class is empty.
}
class Parent
{
public List<Seller> Seller
{
get;
set;
}
public string Id
{
get;
set;
}
}
Am not able to access any properties of parent class . Please help.
unit test code
[Test]
public class test()
{
child a = new child();
a. // not showing any properties of parent
}
if you want to get a.ID , a.Seller you have to declare:
class child :Parent
{
//this class is empty.
}
If you derive from a List<T> you will inherit its abilities, not the abilities from T. What you can do is access one T in the list to access its properties.
public class Parent
{
public bool IAmAParent { get; set; }
}
public class Child : List<Parent>
{ }
var c = new Child();
c[0].IAmAParent = true;
From what I'm seeing I have the feeling you are confused about the inheritance you need. If you need to access the Parent's properties in the Child then it should inherit from the Parent, then put into a list, not the opposite.
public class Parent
{
public bool IAmAParent { get; set; }
}
public class Child : Parent
{ }
var c = new List<Child>();
c[0].IAmAParent = true;
Suppose we have these two classes:
public class Parent
{
public int ID { get; set; }
public virtual ICollection<Child> Children { get; set; }
}
public class Child
{
public int ID { get; set; }
public int ParentID { get; set; }
public virtual Parent Parent { get; set; }
}
Suppose I create one of each with the following methods:
//Create a parent with new children
public void CreateParent(MyDbContext context)
{
context.Parents.Add(new Parent
{
Children = new List<Child>()
{
new Child(),
new Child(),
new Child()
}
});
context.SaveChanges();
}
//Create a child with a new parent
public void CreateChild(MyDbContext context)
{
context.Children.Add(new Child
{
Parent = new Parent()
});
context.SaveChanges();
}
Will either of these methods create both Parent and Child objects with foreign keys appropriately assigned? My gut tells me that CreateParent would work, but CreateChild would not.
Thank you!
Yes, both of these methods will create the Parent and Child records as well with the ParentID foreign key set. If you run e.g. the first one, the result you will get will be the following:
And as another answer states you don't need the ParentID however Entity Framework will recognize it as the Foreign Key used for the Parent association and you don't have to use the virtual keyword neither at the Children nor at the Parent property to make your code work, however if you wan't Lazy Loading to work with these properties you will need them.
Yes both functions work correctly, adding both Parent and Child records with the correct association between them.
Running CreateParent will yield one new Parent record and three Child records associated with it (through ParentID).
Running CreateChild will create one new Child and one new Parent record, associated correctly.