Click here to Skip to main content
15,887,214 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hi,

I am working on a requirement. So, basically there are three entities in EF and lets consider them as:
1) Employee Table (2) Primary_Address Table (3) Secondary_Address Table

Here, Primary_Address Table and Secondary_Address Table are in 1-1 relationship with Employee Table.

I want to create a clone of Employee along with its child objects - Primary_Address and Secondary_Address.

Am using "Deep Cloning" using ICloneable interface. I can be able to clone the "Employee" object but the child objects are always NULL.

What I have tried:

Employee Entity Structure:

C#
;
[Table("Employee")]
public class EmployeeEntity : ICloneable
{
        [Key]
        [Column("Id")]
        public int Id { get; set; }

        [Column("EmployeeName")]
        public string EmployeeName { get; set; }

        public PrimaryAddressEntity PrimaryAddress { get; set; }
        public SecondaryAddressEntity SecondaryAddress { get; set; }

        public EmployeeEntity Clone() { return (EmployeeEntity)this.MemberwiseClone(); }
        object ICloneable.Clone() { return Clone(); }

}


Primary Address Entity Structure:

C#
[Table("PrimaryAddress")]
public class PrimaryAddressEntity
{
        [Key]
        [Column("PrimaryAddrId")]
        public int PrimaryAddrId { get; set; }

        [Key]
        [Column("PrimaryAddrDesc")]
        public string PrimaryAddrDesc { get; set; }

        [Column("EmployeeId")]        
        public int EmployeeId { get; set; }

        [ForeignKey("EmployeeId")]
        public EmployeeEntity Employee  { get; set; }

}


Secondary Address Entity Structure:

C#
[Table("SecondaryAddress")]
public class SecondaryAddressEntity
{
        [Key]
        [Column("SecondaryAddrId")]
        public int SecondaryAddrId { get; set; }

        [Key]
        [Column("SecondaryAddrDesc")]
        public string SecondaryAddrDesc { get; set; }

        [Column("EmployeeId")]        
        public int EmployeeId { get; set; }

        [ForeignKey("EmployeeId")]
        public EmployeeEntity Employee  { get; set; }

}


Now, in "cloning" operation, am doing like this to test if everything is working fine or not:

C#
EmployeeEntity testObj = FetchEmployee("100");

EmployeeEntity cloneTestObj = testObj.Clone();
cloneTestObj.Id = 0;
cloneTestObj.EmployeeName = "Agnib";
AddEmployee(cloneTestObj);


C#
public EmployeeEntity FetchEmployee(string empId)
{
  //return dbContext.Employees.Where(e => e.Id == System.Convert.ToInt32(empId)).FirstOrDefault();

  return dbContext.Employees.Where(e => e.Id == System.Convert.ToInt32(empId)).Include(p=>p.PrimaryAddress).Include(s=>s.SecondaryAddress).FirstOrDefault();
}


C#
public bool AddEmployee(EmployeeEntity employeeEntity)
{
  dbContext.Employees.Add(employeeEntity);
  return dbContext.SaveChanges() > 0;
}


In this approach, I can be able to create a clone of the Employee object but the child objects (PrimaryAddress and SecondaryAddress) are coming as NULL while am fetching on the basis of EmployeeId.

I must be doing something wrong but cannot be able to figure it out.
So, if anyone can help me in this.

Thank you all.
Take care.
Posted
Updated 12-Apr-21 16:07pm
v2

1 solution

You'll need to clone those properties in the clone method yourself. There is an example of a shallow and deep clone in this link

Object.MemberwiseClone Method (System) | Microsoft Docs[^]
 
Share this answer
 
Comments
Member 11072126 13-Apr-21 0:40am    
Thanks for the response.
So, it means I need to clone separately those two child objects as I did for the Employee class? This came to my mind earlier.

But, am fetching the Employee records and applying "include" over there to fetch all the related objects too. Then why "include" is not working?
F-ES Sitecore 13-Apr-21 22:02pm    
Actually now I think about it as these are EF entities the problem might be that you're using proxy objects in EF. Try disabling proxy generation

https://docs.microsoft.com/en-us/dotnet/api/system.data.entity.infrastructure.dbcontextconfiguration.proxycreationenabled?view=entity-framework-6.2.0

and if the clone works after that then that's your problem. Either leave proxies off or if you want to close the proxied object you won't be able to use memberwiseclone at all, you'll literally need to copy the properties across from the original to a new object you crated. If you're using something like AutoMapper then it can do that for you, or you can use reflection

Reflection example

or just manually copy properties but that's pretty tedious. You can just re-get the items from the database, that's another option.
Member 11072126 13-Apr-21 13:10pm    
Can you please share me something as how to clone those properties from the Employee clone method itself? Thanks.
Member 11072126 14-Apr-21 6:01am    
Hi, I tried the below way and am getting "Object reference not set to an instance of an object."

EmployeeEntity cloneTestObj = testObj.Clone();
cloneTestObj.Id = 0;
cloneTestObj.EmployeeName = "Agnib";

// throwing Null exception
cloneTestObj.PrimaryAddress = (PrimaryAddressEntity)testObj.PrimaryAddress.Clone();
AddEmployee(cloneTestObj);

Secondly, PrimaryAddress contain the EmployeeId, so unless I add a clone of an employee, I cannot get the EmployeeId and then how can I set the EmployeeId to Primary and Secondary address entities.
F-ES Sitecore 14-Apr-21 6:08am    
Is testObj.PrimaryAddress null in the line that throws the exception?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900