Creating Org Structure from An Employee Class - c#

I have the following class:
public class Employee
{
public int EmployeeID { get; set; }
public string EmployeeName { get; set; }
public string EmployeeLastname { get; set; }
public int ManagerID { get; set; }
public Employee Manager { get; set; }
public string Department { get; set; }
}
And the following objects:
Employee emp1 = new Employee();
emp1.Department = "C Level";
emp1.EmployeeID = 1;
emp1.EmployeeLastname = "Smith";
emp1.EmployeeName = "Joe";
Employee emp2 = new Employee();
emp2.Department = "B Level";
emp2.EmployeeID = 2;
emp2.EmployeeLastname = "Smith";
emp2.EmployeeName = "John";
emp2.ManagerID = 1;
Employee emp3 = new Employee();
emp3.Department = "A Level";
emp3.EmployeeID = 3;
emp3.EmployeeLastname = "Mallari";
emp3.EmployeeName = "Lem";
emp3.ManagerID = 2;
I need to create a method which needs an employee id and returns a single Employee object which contains the org structure. So for example if I search for employee 1 it returns me the following:
Employee
EmployeeID: 1
EmployeeName: Joe
EmployeeLastName: Smith
Department: C Level
ManagerID: null
Manager: null
But for example if I search for Employee ID 3 it will return me the following:
Employee
EmployeeID: 3
EmployeeName: Lem
EmployeeName: Mallari
Department: A Level
ManagerID: 2
Manager:
EmployeeID: 2
EmployeeName: John
EmployeeLastname: Smith
Department: B Level
ManagerID: 1
Manager:
EmployeeID: 1
EmployeeName: Joe
EmployeeLasname: Smith
Department: C Level
ManagerID: null
Manager: null
I was able to create a method already which gets the details of the manager given an ID and link that manager to the employee originally searched. I just can't think of a way to continuously search for a manager and updating the property of an object an be able to create the structure I need.

One solution would be to use recursion to reconstruct the object graph. Downside is that you would need all employees in memory.
public class EmployeeSearcher
{
private IEnumerable<Employee> _employees;
public EmployeeSearcher(IEnumerable<Employee> employees) => _employees = employees;
public Employee Search(int id)
{
var employee = _employees.SingleOrDefault(e => e.EmployeeID == id);
if (employee == null) throw new Exception($"Employee not found: {id}");
FindManagerRecursive(employee);
return employee;
}
private void FindManagerRecursive(Employee employee)
{
if (!employee.ManagerID.HasValue) return;
var manager = _employees.SingleOrDefault(e => e.EmployeeID == employee.ManagerID.Value);
if (manager == null) throw new Exception("Manager not found: {employee.ManagerID}");
employee.Manager = manager;
FindManagerRecursive(manager);
}
}
Usage:
var searcher = new EmployeeSearcher(new List<Employee> { emp1, emp2, emp3});
var result = searcher.Search(3);

Your requirement is already in C#.
var employee3 = emps.FirstOrDefault(x => x.EmployeeID == 3);
Your employee3 contains already all the information of the managers.
var manager = employee3?.Manager?.Manager;

Have a look at below at any point you will know who all are the employees and who is the manager and then with your employee object you can traverse upwards or downwards.
class Program
{
static List<Employee> lstEmployee = new List<Employee>();
static void Main(string[] args)
{
Employee emp1 = new Employee();
emp1.Department = "C Level";
emp1.EmployeeID = 1;
emp1.EmployeeLastname = "Smith";
emp1.EmployeeName = "Joe";
lstEmployee.Add(emp1);
Employee emp2 = new Employee();
emp2.Department = "B Level";
emp2.EmployeeID = 2;
emp2.EmployeeLastname = "Smith";
emp2.EmployeeName = "John";
emp2.ManagerID = 1;
lstEmployee.Add(emp2);
Employee emp3 = new Employee();
emp3.Department = "A Level";
emp3.EmployeeID = 3;
emp3.EmployeeLastname = "Mallari";
emp3.EmployeeName = "Lem";
emp3.ManagerID = 2;
lstEmployee.Add(emp3);
Console.ReadLine();
}
public class Employee
{
public int EmployeeID { get; set; }
public string EmployeeName { get; set; }
public string EmployeeLastname { get; set; }
public int ManagerID { get; set; }
public Employee Manager
{
get
{
return (from a in lstEmployee where a.EmployeeID == ManagerID select a).FirstOrDefault();
}
}
public List<Employee> Reportees
{
get
{
return (from a in lstEmployee where a.ManagerID == EmployeeID select a).ToList();
}
}
public string Department { get; set; }
}
}

Related

How can I join a list of employees and genders using linq

I have retrieve a list of employees. my employee class columns(employeeId, lastname, genderid)
List<m_employees> Items = new List<m_employees>
{
new m_employees{ employeeid = 1, lastname = "mike", genderid = 1 },
new m_employees{ employeeid = 2, lastname = "jeni", genderid = 2 }
};
then i have my gender class columns (id, title)
List<m_genders> genders = new List<m_genders>
{
new m_genders{ id = 1, title = "Male" },
new m_genders{ id = 2, title = "Female" }
};
//then i tried joining the retrieved list of employees to the genders
var x = from emp in Items
join sex in genders
on emp.genderid equals sex.id
into a from b in a.DefaultIfEmpty(new m_genders())
select new
{
emp.lastname,
emp.genderid,
sex = b.title
};
red error line is showing to the keyword join and says "the type of one of the expressions in the join clause is incorrect..."
how can i join them properly?
This happens because types emp.genderid, sex.id are different and you need to cast or convert them explicitly like that:
(int)emp.genderid equals sex.id
I was able to reproduce the error with the following class definition:
class m_genders
{
public int id { get; set; }
public string title { get; set; }
}
class employee
{
public int id;
public uint genderid;
public string lastname { get; set; }
}
Your question is not clear, the code work without any problem :
namespace WindowsFormsApp1
{
public class m_genders
{
public int id;
public string title;
}
public class m_employees
{
public int employeeid { get; set; }
public int genderid { get; set; }
public string lastname { get; set; }
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
List<m_genders> genders = new List<m_genders>
{
new m_genders {id = 1, title = "Male"},
new m_genders {id = 2, title = "Female"}
};
List<m_employees> Items = new List<m_employees>
{
new m_employees{ employeeid = 1, lastname = "mike", genderid = 1 },
new m_employees{ employeeid = 2, lastname = "jeni", genderid = 2 }
};
var x = from emp in Items
join sex in genders
on emp.genderid equals sex.id
into a
from b in a.DefaultIfEmpty(new m_genders())
select new
{
emp.lastname,
emp.genderid,
sex = b.title
};
}
}
}

Linq - populate lists with outer joins data

Is is possible to have a linq query that populates a class with List for any outer join subqueries?
I've tried various variations of this, but can't get it to work.
Another option would be to populate the class by having more queries, but that would be bad performance wise.
Here's an example, where I try to populate MyClass, using a single query
var result = from p in PersonTable
join cars in CarTable on p.id equals cars.id_person into carsGroup.DefaultIfEmpty()
select new MyClass
{
Person = new Person
{
Id = p.id,
Name = p.name
},
Cars = new List<Car>()
{
Id = carsGroup....??
}
}
public class MyClass
{
public Person Person { get; set; }
public List<PersonCar> Cars { get; set; }
}
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
public class PersonCar
{
public int Id { get; set; }
pubint int IdPerson {get; set;}
public string Description { get; set; }
}
The LINQ query you have provide is incorrect. The following is a Test that will demonstrate functionality that you're probably looking for:
[TestMethod]
public void TestMethod1()
{
var PersonTable = new List<Person>
{
new Person
{
Id = 1,
Name = "Test1"
},
new Person
{
Id = 2,
Name = "Test2"
},
};
var CarTable = new List<PersonCar>
{
new PersonCar
{
Id = 1,
IdPerson = 2
},
new PersonCar
{
Id = 2,
IdPerson = 3
}
};
var result = (from person in PersonTable
join cars in CarTable on person.Id equals cars.IdPerson into carsGroup
from args in carsGroup.DefaultIfEmpty()
select new MyClass
{
Person = person,
Cars = carsGroup.ToList()
}).ToList();
Assert.AreEqual(2, result.Count);
Assert.AreEqual(1, result.Count(res => res.Cars.Count == 0));
Assert.AreEqual(1, result.Count(res => res.Cars.Count == 1));
}

Linq : Comparing 1 Child Collection to (Aggregated) ChildCollection(s)

I have a Linq question: (DotNet Framework 4.0)
I have the following classes:
public class Employee
{
public Guid? EmployeeUUID { get; set; }
public string SSN { get; set; }
}
public class JobTitle
{
public Guid? JobTitleSurrogateKey { get; set; }
public string JobTitleName { get; set; }
}
public class EmployeeToJobTitleMatchLink
{
public EmployeeToJobTitleMatchLink()
{
this.TheJobTitle = new JobTitle() { JobTitleSurrogateKey = Guid.NewGuid(), JobTitleName = "SomeJobTitle:" + Guid.NewGuid().ToString("N") };
}
public Guid LinkSurrogateKey { get; set; }
/* Related Objects */
public Employee TheEmployee { get; set; }
public JobTitle TheJobTitle { get; set; }
}
public class Organization
{
public Organization()
{
this.Links = new List<EmployeeToJobTitleMatchLink>();
}
public int OrganizationSurrogateKey { get; set; }
public ICollection<EmployeeToJobTitleMatchLink> Links { get; set; }
}
In my code below, I can compare 2 child-collections and get the results I need (in "matches1".
Here I am using the "SSN" string property to compare and find the overlaps. And the Console.Write for matches1 works as I expect.
What I don't know how to do is compare the first child collection (org10) to all the children in (allOtherOrgsExceptOrg10 (all the Organizations and all the Links of these Organizations )
The commented out code shows kinda what I'm trying to do, one of my many feeble attempts today.
But basically, match2 would be populated with all the SSN overlaps...but comparing org10 with allOtherOrgsExceptOrg10, all their "Links", and their Employee.SSN's.
org10 overlaps with org20 with "AAA", so match2 would contain "AAA". and org10 overlaps with org30 with "BBB" so match2 would contain "BBB".
Organization org10 = new Organization();
org10.OrganizationSurrogateKey = 10;
Employee e11 = new Employee() { SSN = "AAA", EmployeeUUID = new Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA") };
EmployeeToJobTitleMatchLink link11 = new EmployeeToJobTitleMatchLink();
link11.TheEmployee = e11;
org10.Links.Add(link11);
Employee e12 = new Employee() { SSN = "BBB", EmployeeUUID = new Guid("BBBBBBBB-BBBB-BBBB-BBBB-BBBBBBBBBBBB") };
EmployeeToJobTitleMatchLink link12 = new EmployeeToJobTitleMatchLink();
link12.TheEmployee = e12;
org10.Links.Add(link12);
Organization org20 = new Organization();
org20.OrganizationSurrogateKey = 20;
Employee e21 = new Employee() { SSN = "AAA", EmployeeUUID = new Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA") };
EmployeeToJobTitleMatchLink link21 = new EmployeeToJobTitleMatchLink();
link21.TheEmployee = e21;
org20.Links.Add(link21);
Employee e22 = new Employee() { SSN = "CCC", EmployeeUUID = new Guid("CCCCCCCC-CCCC-CCCC-CCCC-CCCCCCCCCCCC") };
EmployeeToJobTitleMatchLink link22 = new EmployeeToJobTitleMatchLink();
link22.TheEmployee = e22;
org20.Links.Add(link22);
Organization org30 = new Organization();
org30.OrganizationSurrogateKey = 30;
Employee e31 = new Employee() { SSN = "BBB", EmployeeUUID = new Guid("BBBBBBBB-BBBB-BBBB-BBBB-BBBBBBBBBBBB") };
EmployeeToJobTitleMatchLink link31 = new EmployeeToJobTitleMatchLink();
link31.TheEmployee = e31;
org30.Links.Add(link31);
Employee e32 = new Employee();
e32.SSN = "ZZZ";
EmployeeToJobTitleMatchLink link32 = new EmployeeToJobTitleMatchLink();
link32.TheEmployee = e32;
org30.Links.Add(link32);
IList<Organization> allOtherOrgsExceptOrg10 = new List<Organization>();
/* Note, I did not add org10 here */
allOtherOrgsExceptOrg10.Add(org20);
allOtherOrgsExceptOrg10.Add(org30);
IEnumerable<EmployeeToJobTitleMatchLink> matches1 =
org10.Links.Where(org10Link => org20.Links.Any(org20Link => org20Link.TheEmployee.SSN.Equals(org10Link.TheEmployee.SSN, StringComparison.OrdinalIgnoreCase)));
IEnumerable<EmployeeToJobTitleMatchLink> matches2 = null;
//org10.Links.Where(org10Link => ( allOtherOrgs.Where ( anyOtherOrg => anyOtherOrg.Links.Any(dbSideChild => dbSideChild.TheEmployee.SSN == org10Link.TheEmployee.SSN)) );
if (null != matches1)
{
foreach (EmployeeToJobTitleMatchLink link in matches1)
{
Console.WriteLine(string.Format("matches1, SSN = {0}", link.TheEmployee.SSN));
}
}
if (null != matches2)
{
foreach (EmployeeToJobTitleMatchLink link in matches2)
{
Console.WriteLine(string.Format("matches2, SSN = {0}", link.TheEmployee.SSN));
}
}
matches2 =
allOtherOrgsExceptOrg10.SelectMany(x => x.Links)
.Where(x => org10.Links.Select(o => o.TheEmployee.SSN).Contains(x.TheEmployee.SSN));
You can use the SelectMany on the allOther collection to select all Links over all org's. Then check if any SSN is inside the org10 List.
See: http://msdn.microsoft.com/en-us/library/system.linq.enumerable.selectmany(v=vs.100).aspx
You can use SelectMany to flatten out the collection and then use it just like you have for matches1
IEnumerable<EmployeeToJobTitleMatchLink> matches2 =
org10.Links.Where(
org10Link =>
allOtherOrgsExceptOrg10.SelectMany(allOtherOrgs => allOtherOrgs.Links).Any(
anyOtherLink =>
anyOtherLink.TheEmployee.SSN.Equals(org10Link.TheEmployee.SSN, StringComparison.OrdinalIgnoreCase)));
The SelectMany will make it seem like one IEnumerable instead of and IEnumerable of an IEnumerable.

AutoMapper Map object to array

I have an entity called ActionResult that my methods along the application returns. Now i want to map a returned object in the ActionResult to it's right place in an array of that object...
public class Core
{
public Employee[] Employees = new[] {
new Employee {
Name = "Jack",
Age = 21,
Salary = 1000
},
new Employee {
Name = "Carl",
Age = 35,
Salary = 1000
},
new Employee {
Name = "Tom",
Age = 41,
Salary = 1000
},
};
}
public class ActionResult
{
public string ActionID { get; set; }
public Employee Employee { get; set; }
}
public class Employee
{
public String Name { get; set; }
public int? Age { get; set; }
public int? Salary { get; set; }
public int? Level { get; set; }
}
public ActionResult MethodThatReturnsActionResultWithAnEmployee()
{
return new ActionResult {
ActionID = new Guid().ToString(),
Employee = new Employee {
Name = "Carl",
Age = 35,
Salary = 7000,
Level = 1
}
};
}
Now as you can see what i want to do is taking the Employee that is returned from the Method, and search in the array of Employees in the Core and update it using the new given data using AutoMapper.
AutoMapper will not search employee in some array for you. How it would know which employees should be considered as equal? You should search for employee manually, and use appropriate mapping method to update existing instance of employee with data from other employee instance:
Mapper.CreateMap<Employee, Employee>();
var result = MethodThatReturnsActionResultWithAnEmployee();
var employee = result.Employee;
var core = new Core();
var employeeToUpdate =
core.Employees.FirstOrDefault(e => e.Name == employee.Name);
Mapper.Map(employee, employeeToUpdate);
If you really want mapping to look like
Mapper.Map(result, core);
Then you should write your own type mapper for this:
public class ActionResultToCoreConverter : ITypeConverter<ActionResult, Core>
{
public Core Convert(ResolutionContext context)
{
var result = (ActionResult)context.SourceValue;
var employee = result.Employee;
var core = (Core)context.DestinationValue ?? new Core();
var employeeToUpdate =
core.Employees.FirstOrDefault(e => e.Name == employee.Name);
Mapper.Map(employee, employeeToUpdate);
return core;
}
}
And mapping will look like:
Mapper.CreateMap<Employee, Employee>(); // this map also required
Mapper.CreateMap<ActionResult, Core>()
.ConvertUsing<ActionResultToCoreConverter>();
var result = MethodThatReturnsActionResultWithAnEmployee();
var core = new Core();
Mapper.Map(result, core);
// if you want to create new Core instanse:
var core2 = Mapper<Core>(result);

Question about Auto-Implemented Properties C#

I have this code:
void Main()
{
List<Employee> employeeList;
employeeList = new List<Employee>
{
{new Employee("000001", "DELA CRUZ, JUAN T.")},
{new Employee("000002", "GOMEZ, MAR B.")},
{new Employee("000003", "RIVERA, ERWIN J.")}
};
employeeList.Dump();
}
public class Employee
{
public string EmployeeNo { get; set; }
public string Name { get; set; }
public Employee(string employeeNo, string name)
{
this.EmployeeNo = employeeNo;
this.Name = name;
}
}
How should I make a new instance of Employee class using the properties only and add that instance to the employeeList (I mean not using the class constructor of employee)?
I already made a solution but it's too lengthy. How should I shorten it?
void Main()
{
List<Employee> employeeList;
#region - I want to shorten these lengthy codes.
Employee employee1 = new Employee();
employee1.EmployeeNo = "000001";
employee1.Name = "DELA CRUZ, JUAN T.";
Employee employee2 = new Employee();
employee2.EmployeeNo = "000002";
employee2.Name = "GOMEZ, MAR B.";
// other employees...
#endregion
employeeList = new List<Employee>
{
employee1,
employee2
};
employeeList.Dump();
}
public class Employee
{
public string EmployeeNo { get; set; }
public string Name { get; set; }
}
You could do this
var list = new List<Employee>
{
new Employee {EmployeeNo = "000001", Name = "Peter Pan"},
new Employee {EmployeeNo = "000002", Name = "King Kong"}
};
of this
public class EmployeeList : List<Employee>
{
public void Add(string no, string name)
{
this.Add(new Employee(no, name));
}
}
var list = new EmployeeList
{
{ "000001", "Peter Pan" },
{ "000002", "King Kong"}
};
You could do something like that
var employee1 = New Employee() { EmployeeNo = "000001", Name = "DELA CRUZ, JUAN T." };
How about this?
void Main()
{
var employeeList = new List<Employee> {
new Employee { EmployeeNo = "000001", Name = "DELA CRUZ, JUAN T." },
new Employee { EmployeeNo = "000002", Name = "GOMEZ, MAR B." }
};
employeeList.Dump();
}
public class Employee
{
public string EmployeeNo { get; set; }
public string Name { get; set; }
}

Categories

Resources