How to perform LINQ on IEnumerable<Employee> / IEnumerable<object>? - c#

I have
IEnumerable<Employee> GetAllEmployees()
{
return Get<IEmployeeRepository>().GetAll();
}
Where IEmployeeRepository is
public interface IEmployeeRepository
{
IEnumerable<Employee> GetAll();
}
Employee.cs is as under
public class Employee
{
public int EmployeeId { get; set; }
public string EmployeeName { get; set; }
public int Age { get; set; }
public int Salary { get; set; }
}
Now I want to perform a search on the records obtained from GetAllEmployees() based on the EmployeeId passed. Like as under
public void SearchEmployee(int empId)
{
var empRecords = this.GetAllEmployees();
var filteredRecords = empRecords.
}
I actually looked into this answer but could not fit into the requirement.
What I need to do?

I just figured out that the namespace System.Linq is missing.
Else we could even do
foreach (var item in empRecords)
{
//
}
I will give the credit to # Jenish Rabadiya, though others have also given correct opinion.

This is the object first you need to convert to list of object and then try to cast it.
(empRecords as IEnumerable<object>).Cast(....)

Related

Generic list of generic lists

I've been playing with various ways of using generics and have hit a road block.
Consider the following classes:
public abstract class DataElement
{
public int Id { get; set; }
}
public class School : DataElement
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
}
public class Course : DataElement
{
public int Id { get; set; }
public int SchoolId { get; set; }
public string Name { get; set; } = string.Empty;
}
public class Student : DataElement
{
public int Id { get; set; }
public int CourseId { get; set; }
public string Name { get; set; } = string.Empty;
public string Phone { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
}
Considering a hypothetical scenario where none of this data changes, I'm trying to create a DataDictionary class to house those objects in their respective Lists all within one top-level List property. This crazy idea came to me, when I was writing code to load the different data types from JSON files. I was able to write one load method that could read all three types of data using generics, and that sent me down this particular rabbit hole.
public interface IDataDictionary
{
public List<T> GetAllItemsFromList<T>();
public T GetSingleItemFromList<T>(int id);
}
public class DataDictionary : IDataDictionary
{
public List<IList> Data = new List<IList>();
// Return all objects from the list of type T
public List<T> GetAllItemsFromList<T>()
{
return Data.OfType<T>().ToList(); // This works, returning the appropriate list.
}
// Return specific object from the list of type T by Id property value
public T GetSingleItemFromList<T>(int id)
{
List<T> list = Data.OfType<List<T>>().First(); // This works, resolving to the correct list (e.g. Courses).
return list.Where(i => i.Id == id).First(); // This doesn't work. It doesn't appear to know about the Id property in this context.
}
}
GetAllItemsFromList works fine, returning the appropriate list of items
List<School> newList = GetAllItemsFromList<School>();
However, I am unable to figure out how to return a single item by Id from its respective list.
School newSchool = GetSingleItemFromList<School>(1);
It could be that I'm just trying to be too clever with this, but I can't help but think there is a way to do this, and I'm just missing it.
This doesn't work. It doesn't appear to know about the Id property in this context.
Yes, because you have not specified any constraints to the type parameter T, so it can be anything. There are multiple options:
Create an interface IHaveId and constraint T to it (or use DataElement):
public interface IHaveId
{
int Id { get; set; }
}
public interface IDataDictionary
{
public List<T> GetAllItemsFromList<T>();
public T GetSingleItemFromList<T>(int id) where T : IHaveId; // or where T : DataElement
}
public class DataDictionary : IDataDictionary
{
public T GetSingleItemFromList<T>(int id) where T : IHaveId // or where T : DataElement
{
List<T> list = Data.OfType<List<T>>().First();
return list.Where(i => i.Id == id)
.First();
}
}
add additional parameter to select the id:
public T GetSingleItemFromList<T>(int id, Func<T, int> idSelector)
{
List<T> list = Data.OfType<List<T>>().First();
return list.First(i => idSelector(i) == id);
}
use reflection - I would argue the least recommended option
The problem is that T parameter in function GetSingleItemFromList<T>(int id) could be anything. In order of this to work you should add a constraint:
GetSingleItemFromList<T>(int id) where T: DataElement

How to obtain an object with mongodb driver 3.4.2 from c#

I have problems to obtains objects in C#. I use mongo driver 2.4.3.
I have this code:
public Employee GetEmployee(int id)
{
IMongoCollection<Employee> collection = conectWithDatabase();
var filter = Builders<Employee>.Filter.Eq("EmployeeId", id);
var obtenido = collection.Find(filter).First();
return obtenido;
}
and this
public List<Employee> GetAllEmployees()
{
IMongoCollection<Employee> collection = conectWithDatabase();
var query = from employee in collection.AsQueryable<Employee>()
select employee;
return query.ToList();
}
In the first code when I call GetEmplyee method the program show this exception
System.InvalidOperationException: 'No se pueden crear las instancias de
clases abstractas.' -> in this line collection.Find(filter).First();
And in the second code the program show the same exception when i try to cast the query var to list.
I try to get an object from a MongoDB and i can't if someone can help me i will be very grateful.
Sorry my bad english.
public abstract class Employee
{
public int EmployeeId { get; set; }
public string Name { get; set; }
public DateTime StartDate { get; set; }
}
public class FullTimeEmployee : Employee
{
public int Salary { get; set; }
}
public class PartTimeEmployee : Employee
{
public double HourlyRate { get; set; }
}
At a basic level.. You need to map the discriminator column and then match type based on that.
Driver should be able to do this for you
Inheritance in MongoDb: how to request instances of defined type

What is the best way to load data to the following structure from database?

The database schema is as follows
Employee
EmployeeID(int, pk)
FirstName(nvarchar)
LastName(nvarchar)
Email(nvarchar)
EmployeeType(int)
Salary(decimal)
HourlyRate(decimal)
Benefits
BenefitID (int, pk)
Benefit (nvarchar)
EmployeeID (int, fk)
Employee table holds all the employee data. Salary field applies to fulltime employee and the hourly rate applies to hourly employee. Benefits only apply to Full Time employee.
I have setup a service class that will return all the employees.
I also want to initialize all the benefits to the Salaried Employee object. I have setup a check for employee-type using a switch statement and then create the instance of the object and add it to the collection.
This will work perfectly.
The issue I have is every time I add a new type of employee then I will have to modify the Employee service and add logic to switch statement to handle the new type of employee. This breaks the open close principle.
My question is what is the best way to load data from the database to the objects in this type of scenario?
public enum EmployeeType
{
FullTime =1,
PartTime =2
}
public class EmployeeBenefit
{
private string _benefit;
private Employee _employee;
public int EmployeeId { get { return Employee.Id; } }
public Employee Employee { get { return _employee; } }
public string Benefit { get { return _benefit; } }
public EmployeeBenefit(Employee emp, string benefit)
{
_benefit = benefit;
_employee = emp;
}
}
public abstract class Employee
{
public int Id { get; set; }
public abstract EmployeeType Type { get; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
}
public class SalariedEmployee: Employee
{
private ICollection<EmployeeBenefit> _benefits;
public SalariedEmployee()
{
_benefits = new List<EmployeeBenefit>();
}
public IEnumerable<EmployeeBenefit> Benefits { get {return _benefits;} }
public double Salary { get; set; }
public override EmployeeType Type
{
get { return EmployeeType.FullTime; }
}
public void AddBenefit(string benefit)
{
EmployeeBenefit ebenefit = new EmployeeBenefit(this, benefit);
if (Benefits.Contains(ebenefit))
_benefits.Add(ebenefit);
}
public void RemoveBenefit(string benefit)
{
EmployeeBenefit ebenefit = new EmployeeBenefit(this, benefit);
if(_benefits.Contains(ebenefit))
_benefits.Remove(ebenefit);
}
}
public class PartTimeEmployee : Employee
{
public override EmployeeType Type
{
get { return EmployeeType.PartTime; }
}
public double HourlyRate { get; set; }
}
public class EmployeeService
{
public IEnumerable<Employee> GetAll() {
List<Employee> _lst = new List<Employee>();
using(var db = new EmployeeContext)
{
foreach(Employee e in db.Employees)
{
switch(e.Type){
case EmployeeType.PartTime:
PartTimeEmployee pt = new PartTimeEmployee();
//initialize the values of parttime employee like hourly rate
_lst.Add(pt);
break;
case EmployeeType.FullTime:
SalariedEmployee se = new SalariedEmployee();
//initialize the value of salaried employees like benefits, salary
_lst.Add(se);
break;
}
}
}
return _lst;
}
}
What you can do is simply keep the employee type as String attribute in the Employee class , and add the types dynamically to the Employee class. I don't see the actual need of an Employee Type class here.
If you absolutely need such a class, declare it as a class and not an enum, and have a string attribute which will be the name of the type. After that with every new type you get from the query, initialize an new EmployeeType() and add that string with a setter. Then set that EmployeeType to the Employee class.
According to me that is a much better design because you won't need to hard code the string values in the enums.
And for the benefit thing, what you can do is have a benefits attribute to the concrete Employee class(or name it something else as you already have an abstract Employee). And set a value to the benefit only if the type of employee is salaried. That's how I would do it.

Null list after query

I have a problem where I create an object containing a list, load it into my database, run a query that returns the object, but find the list null. All other properties of the object are as they should be. I'm using a list called "Ints" that is filled with a few integers but I've tried using other types.
Here's my model:
public class CourseModel
{
public int CourseModelId { get; set; }
public virtual ICollection<int> Ints { get; set; } // the variable in question
public string Name { get; set; }
public string Overview { get; set; }
}
And here's my database population (The database is called LearnYou):
public class LearnYouDbContextInitializer : DropCreateDatabaseAlways<LearnYouDbContext>
{
protected override void Seed(LearnYouDbContext context)
{
context.Courses.Add(new CourseModel()
{
Name = "C# Programming",
Overview = "You'll learn some C#",
Ints = new List<int> { 1, 42, 3 },
});
context.SaveChanges();
}
}
Here's the controller code for querying the object:
// GET: Course/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
CourseModel courseModel = db.Courses.Find(id);
// DEBUGGING THE PREVIOUS LINE SHOWS INTS IS NULL
if (courseModel == null)
{
return HttpNotFound();
}
return View(courseModel);
}
The "Ints" property is not null after saving the context in the database population part but is always null when it's queried (I visit the page ~Edit/1 to debug). I just can't figure out why when all other properties are fine. Any ideas? Thanks.
An ICollection in a model indicates a Parent->Child relationship. However, I doubt EF will be able to determine how to create a child table for an ICollection of integers. Here is what I would do.
Create a new model Ints (or whatever it actually represents):
public class Ints {
public int Value { get; set;}
}
Modify your original model to use it:
public class CourseModel
{
public int CourseModelId { get; set; }
public virtual ICollection<Ints> Ints { get; set; } // See the difference?
public string Name { get; set; }
public string Overview { get; set; }
}
That should make it work.
It Is not working because you are mapping directly to a int primitive type of .net and Entity Framework doesn't allow it.
In this case what you can do is create your onw object for example and sql table like
public class Ints {
{
public Course Course { get; set; }
public int IntValue { ger; set ; }
}
And referencing it from CourseModel
public virtual List<Ints> Ints { get; set; }

How can I use Equals or hashcode in my following program

I want to fetch the details of manager from manager class if at run time I give kinid of employee from the employee class. How can I do this using Equals or Hashcode?
public class employee
{
public string empname { get; set;}
public string location { get; set; }
public int kinid { get; set; }
public double magkin { get; set; }
}
public class manager
{
public string magname { get; set; }
public double magkin { get; set; }
}
Dictionary<employee, manager> relation = new Dictionary<employee, manager>();
I haven't used C# in a long time, but Something like this should work:
kinidFind is the kinid you want to search for.
manager findManager(int kinidFind) {
foreach( KeyValuePair<employee, manager> i in relation) {
if (i.Key.kinid==kinidFind) {
return i.Value;
}
}
}
Assuming that kinid is a unique identifier (you don't care about other fields of employee in identifying), then on employee class you could do the following:
override int GetHashCode()
{
return kinid;
}
override bool Equals(Object obj)
{
if (obj == null) return false;
emploee emp = obj as employee;
if ((System.Object)emp == null) return false;
return (kinid == emp.kinid);
}
However, this is not a good general solution because what if later on you want to find the employee by other fields?
Consider changing that dictionary to:
Dictionary<int,manager> where the int is the kinid of the employee then it's self explanatory.
or since the Dictionary has been loaded you can Enumerate it this way as well it's just a question of feel or taste at this point from Brads answer
foreach (var pair in relation)
{
if (pair.key == kinidFind )
{
return relation[pair.key];
}
}

Categories

Resources