How to seed a table with data from another table - c#

I made a simple website in ASP.NET Core with Entity Framework where you can manage employees. You have and Employee controller, those Employees belong to a specific department, and there are groups who are assigned to tasks and every kind of employee can be on it from every department.
Here is my seeding:
modelBuilder.Entity<Employee>()
.HasData(
new Employee() { Id = -99, Name = "Mary", Email = "mary#gmail.com", DepartmentId = -99, GroupId = -1 },
new Employee() { Id = -98, Name = "Stan", Email = "stan#gmail.com", DepartmentId = -99, GroupId = -1 },
new Employee() { Id = -97, Name = "Mike", Email = "mike#gmail.com", DepartmentId = -99, GroupId = -1 });
modelBuilder.Entity<Department>()
.HasData(
new Department() { DepartmentId = -99, Field = "IT", Name = "Programming Department" },
new Department() { DepartmentId = -98, Field = "HR", Name = "Human Resorcues" },
new Department() { DepartmentId = -97, Field = "AD", Name = "Advertisement Department" });
modelBuilder.Entity<Group.Group>()
.HasData(
new Group.Group() { GroupId = -1, Name = "Cleaner", Task = "Clean the building"}
);
The thing is, I want that 1 group to have Employees in it, but I don't know how to seed those employees which are added before with Id -99,-98 and -97.
EDIT: Here I tried to make a list of my Employees and add them to the Employees field in Group:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var emp1 = new Employee() { Id = -99, Name = "Mary", Email = "mary#gmail.com", DepartmentId = -99, GroupId = -1 };
var emp2 = new Employee() { Id = -98, Name = "Stan", Email = "stan#gmail.com", DepartmentId = -99, GroupId = -1 };
var emp3 = new Employee() { Id = -97, Name = "Mike", Email = "mike#gmail.com", DepartmentId = -99, GroupId = -1 };
List<Employee> empList = new List<Employee>() { emp1, emp2, emp3 };
modelBuilder.Entity<Employee>()
.HasData(empList);
modelBuilder.Entity<Department>()
.HasData(
new Department() { DepartmentId = -99, Field = "IT", Name = "Programming Department" },
new Department() { DepartmentId = -98, Field = "HR", Name = "Human Resorcues" },
new Department() { DepartmentId = -97, Field = "AD", Name = "Advertisement Department" });
modelBuilder.Entity<Group.Group>()
.HasData(
new Group.Group() { GroupId = -1, Name = "Cleaner", Task = "Clean the building", Employees = empList }
);
}
But I get this error:
The seed entity for entity type 'Group' cannot be added because it has the navigation 'Employees' set. To seed relationships, you need to add the related entity seed to 'Employee' and specify the foreign key values {'GroupId'}. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the involved property values.
EDIT: Here is the seeding method:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Employee>()
.HasData(
new Employee() { Id = -99, Name = "Mary", Email = "mary#gmail.com", DepartmentId = -99, GroupId = -1 },
new Employee() { Id = -98, Name = "Stan", Email = "stan#gmail.com", DepartmentId = -99, GroupId = -1 },
new Employee() { Id = -97, Name = "Mike", Email = "mike#gmail.com", DepartmentId = -99, GroupId = -1 });
modelBuilder.Entity<Department>()
.HasData(
new Department() { DepartmentId = -99, Field = "IT", Name = "Programming Department" },
new Department() { DepartmentId = -98, Field = "HR", Name = "Human Resorcues" },
new Department() { DepartmentId = -97, Field = "AD", Name = "Advertisement Department" });
modelBuilder.Entity<Department>()
.HasMany(a => a.Employees);
modelBuilder.Entity<Group>()
.HasData(
new Group() { GroupId = -1, Name = "Cleaner", TodoId = -99 }
);
modelBuilder.Entity<Group>()
.HasMany(a => a.Employees);
modelBuilder.Entity<Todo>()
.HasData(
new Todo() { ProblemId = -99, Title = "Spilled drink in basement", Descrpition = "Someone spilled drink all over the place in the basement", IsDone = false, GroupId = -1 });
modelBuilder.Entity<Todo>()
.HasOne(a => a.Group);
}
Here is my Group.cs :
public class Group
{
[Key]
public int GroupId { get; set; }
[Required]
public string Name { get; set; }
public int TodoId { get; set; }
public Todo problem;
public List<Employee> Employees { get; set; } = new List<Employee>();
}
and my Employee.cs:
public class Employee
{
public int Id { get; set; }
[Required]
[MaxLength(50, ErrorMessage = "Name cannot exceed 50 characters")]
public string Name { get; set; }
[Required]
[RegularExpression(#"^[a-zA-Z0-9_0+-]+#[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$", ErrorMessage = "Invalid Email Format")]
[Display(Name = "Office Email")]
public string Email { get; set; }
public int DepartmentId { get; set; }
public Department Department { get; set; }
public int GroupId { get; set; }
public Group Group { get; set; }
}
The way I found out that nothing is in the Employees list is I logged out context.Employees.Count in the details function in the controller itself and it said 0

Related

LINQ - Join with List

I have condition where i have to join two different types of array to form a new array.
Let's see the class where condition should be created.
public class MutualFundParameter
{
public int Id { get; set; }
public string AcNo { get; set; }
public string CustomerName { get; set; }
}
public class VoucherDetails
{
public int Id { get; set; }
public int AcNo { get; set; }
public decimal Amount { get; set; }
public int MasterId { get; set; }
}
public class VoucherMaster
{
public int Id { get; set; }
public DateTime DateTime { get; set; }
public ICollection<VoucherDetails> VoucherDetails { get; set; }
}
New let's add some data into that object
// mutual fund parameter
var mutualFundParameters = new List<MutualFundParameter>
{
new MutualFundParameter { Id = 1, AcNo = "001", CustomerName = "Ram" },
new MutualFundParameter { Id = 2, AcNo = "002", CustomerName = "Shyam" },
new MutualFundParameter { Id = 3, AcNo = "003", CustomerName = "Hari" },
new MutualFundParameter { Id = 4, AcNo = "004", CustomerName = "Gita" },
new MutualFundParameter { Id = 5, AcNo = "005", CustomerName = "Sita" },
};
// voucher details
var voucherDetails = new List<VoucherDetails>
{
new VoucherDetails { Id = 1, AcNo = 001, Amount = 10.00M, MasterId = 1 },
new VoucherDetails { Id = 2, AcNo = 001, Amount = 120.00M, MasterId = 1 },
new VoucherDetails { Id = 3, AcNo = 002, Amount = 20.00M, MasterId = 1 },
new VoucherDetails { Id = 4, AcNo = 002, Amount = 120.00M, MasterId = 1 },
new VoucherDetails { Id = 5, AcNo = 002, Amount = 30.00M, MasterId = 1 },
new VoucherDetails { Id = 6, AcNo = 002, Amount = 20.00M, MasterId = 1 },
new VoucherDetails { Id = 7, AcNo = 003, Amount = 20.00M, MasterId = 1 },
new VoucherDetails { Id = 8, AcNo = 003, Amount = 20.00M, MasterId = 1 },
new VoucherDetails { Id = 9, AcNo = 003, Amount = 20.00M, MasterId = 1 },
new VoucherDetails { Id = 10, AcNo = 004, Amount = 10.00M, MasterId = 2 },
new VoucherDetails { Id = 11, AcNo = 005, Amount = 20.00M, MasterId = 2 },
new VoucherDetails { Id = 12, AcNo = 006, Amount = 30.00M, MasterId = 2 },
new VoucherDetails { Id = 13, AcNo = 007, Amount = 40.00M, MasterId = 2 },
new VoucherDetails { Id = 14, AcNo = 008, Amount = 50.00M, MasterId = 2 },
new VoucherDetails { Id = 15, AcNo = 009, Amount = 60.00M, MasterId = 2 },
new VoucherDetails { Id = 16, AcNo = 001, Amount = 70.00M, MasterId = 2 },
};
// voucher
var voucherMasters = new List<VoucherMaster>
{
new VoucherMaster
{
Id = 1,
VoucherDetails = voucherDetails
.Where(x => x.MasterId == 1)
.ToList(),
DateTime = DateTime.Now }
};
Now i need to join MutualFundParameter with VoucherDetails but that is inside a list of 'Voucher Master'
To join i have tried this but this doesn't work as expected
var res = voucherMasters.Join(
mutualFundParameters,
voucher => voucher.VoucherDetails.FirstOrDefault().AcNo,
mutual => mutual.AcNo,
(voucher, mutual) => new
{
}
);
Thanks Hoping for positive response.
Assuming that AcNo is of the same type in both mutualFundParameter and voucherDetail, here are two examples querying either in-memory collection or db:
(Note: I've not compiled/run the code so please excuse any syntactical errors)
var resultFromInMemory = (
from vd in voucherMasters.SelectMany(x => x.voucherDetails)
join mfp in mutualFundParameters on mfp.AcNo equals vd.AcNo
select new { vd, mfp });
var resultFromDb = (
from vd in db.voucherDetails
join mfp in db.mutualFundParameters on mfp.AcNo equals vd.AcNo
select new { vd, mfp });
For in-memory collection since you're expecting voucherDetails to be a child collection of voucherMaster, performing a join between mutualFundParameters and voucherDetails requires that voucherDetails is first consolidated into a temporary single collection which .SelectMany helps with
In case of database (assuming relational db) no such intermediate collection would be needed as every entity is a flat table in there.

TypeError: this.model.currentViewData is undefined (In Implimentation of Hierarchical Grid --> Child Grid)

I am implementing a Hierarchy Grid in ASP.Net MVC using syncfusion Grid Control.
I am fetching the data from server side with an ajax call on the expansion of child grid. When i try to expand child grid, the ajax call fetches the data in JSON format and a JavaScript error (TypeError: this.model.currentViewData is undefined) occurs and data in the child grid doesn't load into child grid.
Details of Question and running source code example are also available here.
Classes
public class Data
{
public int OrderID { get; set; }
public int EmployeeID { get; set; }
public string ShipCountry { get; set; }
public List<ChildData> Employee { get; set; }
}
public class ChildData
{
public int EmployeeID { get; set; }
public string FirstNAme { get; set; }
public string LastNAme { get; set; }
}
Controller
public class GridController : Controller
{
//
// GET: /Grid/
List<Data> obj = new List<Data>();
public ActionResult GridFeatures()
{
var DataSource = GetData();
ViewBag.datasource = DataSource.ToList();
return View();
}
public JsonResult GetChildData(int _empID)
{
var ChildDaqtaSource = ChildData(_empID);
return Json(ChildDaqtaSource, JsonRequestBehavior.AllowGet);
}
public static List<Data> GetData()
{
List<Data> obj = new List<Data>();
//obj.Add(new Data() { OrderID = 1000, EmployeeID = 1, ShipCountry = "india", Employee = new List<ChildData>() { new ChildData() { EmployeeID = 1, FirstNAme = "Janet", LastNAme = "David" } } });
//obj.Add(new Data() { OrderID = 1001, EmployeeID = 2, ShipCountry = "France", Employee = new List<ChildData>() { new ChildData() { EmployeeID = 2, FirstNAme = "Nancy", LastNAme = "John" } } });
//obj.Add(new Data() { OrderID = 1002, EmployeeID = 3, ShipCountry = "US", Employee = new List<ChildData>() { new ChildData() { EmployeeID = 3, FirstNAme = "David", LastNAme = "Staven" } } });
//obj.Add(new Data() { OrderID = 1003, EmployeeID = 4, ShipCountry = "US", Employee = new List<ChildData>() { new ChildData() { EmployeeID = 4, FirstNAme = "Janet", LastNAme = "David" } } });
obj.Add(new Data() { OrderID = 1000, EmployeeID = 1, ShipCountry = "india" });
obj.Add(new Data() { OrderID = 1001, EmployeeID = 2, ShipCountry = "France" });
obj.Add(new Data() { OrderID = 1002, EmployeeID = 3, ShipCountry = "US" });
obj.Add(new Data() { OrderID = 1003, EmployeeID = 4, ShipCountry = "US" });
return obj;
}
public static List<ChildData> ChildData(int _EmpID)
{
List<ChildData> _childData = new List<ChildData>();
_childData.Add(new ChildData { EmployeeID = 1, FirstNAme = "John", LastNAme = "Freeman" });
_childData.Add(new ChildData { EmployeeID = 1, FirstNAme = "steve", LastNAme = "Alexander" });
_childData.Add(new ChildData { EmployeeID = 1, FirstNAme = "Ali", LastNAme = "Naeem" });
_childData.Add(new ChildData { EmployeeID = 1, FirstNAme = "Alex", LastNAme = "Wonder" });
_childData.Add(new ChildData { EmployeeID = 1, FirstNAme = "Bill", LastNAme = "Gates" });
_childData.Add(new ChildData { EmployeeID = 1, FirstNAme = "Alan", LastNAme = "Turing" });
_childData.Add(new ChildData { EmployeeID = 2, FirstNAme = "Mark", LastNAme = "Anthoney" });
_childData.Add(new ChildData { EmployeeID = 2, FirstNAme = "Carl", LastNAme = "Shoemaker" });
_childData.Add(new ChildData { EmployeeID = 3, FirstNAme = "Carlos", LastNAme = "Anthony" });
return _childData.Where(x => x.EmployeeID == _EmpID).ToList();
}
}
Razor View (GridFeatures.cshtml)
#model List<RemoteSaveAdaptorSample.Controllers.Data>
<h2>Requisitions</h2>
#(Html.EJ().Grid<RemoteSaveAdaptorSample.Controllers.Data>("EmployeeGrid")
.Datasource((List<RemoteSaveAdaptorSample.Controllers.Data>)ViewBag.DataSource)
//.Datasource(Model)
.AllowSorting(true)
.AllowResizing(true)
.AllowPaging(true)
.AllowGrouping(true)
.AllowTextWrap(true)
.AllowScrolling(true)
.AllowFiltering()
.EnableRowHover(true)
.Columns(col =>
{
col.Field(x => x.EmployeeID).HeaderText("EmployeeID").Width(30).IsPrimaryKey(true).AllowResizing(false).Add();
col.Field(x => x.OrderID).HeaderText("OrderID").Width(60).AllowFiltering(true).Add();
col.Field(x => x.ShipCountry).HeaderText("Country").Width(100).Add();
})
.ChildGrid
//<RemoteSaveAdaptorSample.Controllers.ChildData>
(_childGrid =>
{
_childGrid
.QueryString("EmployeeID")
.AllowPaging()
.Columns(_childCol =>
{
_childCol.Field("EmployeeID").HeaderText("EmployeeID").Add();
_childCol.Field("FirstNAme").HeaderText("First Name").Add();
})
.ClientSideEvents(x => x.Load("loadEvent"))
;
})
)
<script type="text/javascript">
function loadEvent(args) {
var data = this.model.parentDetails.parentKeyFieldValue;
this.model.dataSource = ej.DataManager({
url: "/grid/GetChildData?_empID=" + data + ""
, adaptor: "UrlAdaptor"
});
}
</script>
Any help is appriciated
Thanx
I have checked the query and found that you have returned the result alone from server side instead of passing it as result and count pair. When using UrlAdaptor it is must to return the data as result and count pair. So that it will bind the data to the grid.
Refer the code example
public JsonResult GetChildData(int _empID)
{
var ChildDaqtaSource = ChildData(_empID);
var count = ChildDaqtaSource.Count;
return Json(new { result = ChildDaqtaSource, count = count });
}
Refer the documentation link of UrlAdaptor
Link: https://help.syncfusion.com/aspnetmvc/grid/data-adaptors#url-adaptor

LINQ group list and combine collections

Given these classes:
public class Employee
{
public int EmployeeId { get; set; }
public int GroupId { get; set; }
public List<Plans> Plans { get; set; }
}
public class Plan
{
public int PlanYearId { get; set; }
public string Name { get; set; }
}
And given a setup like so:
var employees = new List<Employee> {
new Employee {
EmployeeId = 1,
GroupId = 1,
Plans = new List<Plan> {
new Plan {
PlanReferenceId = 1111,
Name = "Benefit 1"
}}};
new Employee {
EmployeeId = 1,
GroupId = 1,
Plans = new List<Plan> {
new Plan {
PlanReferenceId= 2222,
Name = "Benefit 2"
},
new Plan {
PlanReferenceId= 2222,
Name = "Benefit 3"
}}}};
How can I use LINQ to group these employees by both EmployeeId and GroupId and then combine the two List<Plan> properties so that i would end up with something like this:
var employee = new Employee
{
EmployeeId = 1,
GroupId = 1,
Plans = new List<Plan> {
new Plan {
PlanReferenceId = 1111,
Name = "Benefit 1"
},
new Plan {
PlanReferenceId = 2222,
Name = "Benefit 2"
},
new Plan {
PlanReferenceId = 2222,
Name = "Benefit 3"
}
}
}
Just use combination of GroupBy and SelectMany:
var result = employees
.GroupBy(e => new { e.EmployeeId, e.GroupId })
.Select(g => new Employee
{
EmployeeId = g.Key.EmployeeId,
GroupId = g.Key.GroupId,
Plans = g.SelectMany(e => e.Plans).ToList()
}).ToList();

Order GroupBy Asc based on Two more Properties using LINQ C#

My GroupBy is performing well. I'm getting the Output
I need to Sort the Group Names
The Brown Color Block, represents the Group.
The Red Color Box within the Brown Color Block, represents the Manager
Peter Block (Brown Box) Should Come first
Raj Block (Brown Box) Should Come Second
Sunny Block (Brown Box) Should Come Third
Each Block Should Group By Boss(Manager) and Assistant (Boss don't have the
SID). After GroupBy the Name should be in Sorted Order, within the Group
the Assistant Names are also in the Sorted Order.
The Model Classes:
public class Person
{
public int ID { get; set; }
public int SID { get; set; }
public string Name { get; set; }
public string Department { get; set; }
public string Gender { get; set; }
public string Role { get; set; }
}
public class Boss
{
public int ID { get; set; }
public int SID { get; set; }
public string Name { get; set; }
public string Department { get; set; }
public string Gender { get; set; }
public string Role { get; set; }
public List<Person> Employees { get; set; }
}
The Main Functionality Source Code:
void Main()
{
List<Boss> BossList = new List<Boss>()
{
new Boss()
{
ID = 101,
Name = "Sunny",
Department = "Development",
Gender = "Male",
Role = "Manager",
Employees = new List<Person>()
{
new Person() {ID = 101, SID = 102, Name = "Peter", Department = "Development", Gender = "Male", Role = "Assistant"},
new Person() {ID = 101, SID = 103, Name = "Emma Watson", Department = "Development", Gender = "Female", Role = "Assistant"},
}
},
new Boss()
{
ID = 104,
Name = "Raj",
Department = "Development",
Gender = "Male",
Role = "Manager",
Employees = new List<Person>()
{
new Person() {ID = 104, SID = 105, Name = "Kaliya", Department = "Development", Gender = "Male", Role = "Assistant"},
new Person() {ID = 104, SID = 103, Name = "Emma Watson", Department = "Development", Gender = "Female", Role = "Assistant"},
},
},
new Boss()
{
ID = 102,
Name = "Peter",
Department = "Development",
Gender = "Male",
Role = "Manager",
Employees = new List<Person>()
{
new Person() {ID = 102, SID = 105, Name = "Kaliya", Department = "Development", Gender = "Male", Role = "Assistant"},
new Person() {ID = 102, SID = 103, Name = "Emma Watson", Department = "Development", Gender = "Female", Role = "Assistant"},
}
}
};
List<Person> EmpList = BossList.SelectMany(i =>
new[] {
new Person()
{
ID = i.ID,
SID = i.SID,
Name = i.Name,
Gender = i.Gender,
Department = i.Department,
Role = i.Role
}
}.Concat(i.Employees)
).ToList().GroupBy(s => s.ID).SelectMany(h => h.GroupBy(g => g.SID).SelectMany(u => u.OrderBy(k=> k.Name))).ToList();
}
You can do by adding the ThenBy extension method after the Order by to apply the secondary sort. In fact, the ThenBy can be called multiple times for sorting on multiple property. I have modified the last line of your code to show how you can achieve this.
).ToList().GroupBy(s => s.ID).SelectMany(h => h.GroupBy(g => g.SID).SelectMany(u => u.OrderBy(k=> k.Name).ThenBy(l => l.<<secondproperty>>))).ToList();
The datastructure already establishes the groups. There is no need to re-group.
List<Person> result = (
from boss in BossList
order by boss.Name
let orderedEmployees = boss.Employees.OrderBy(emp => emp.Name)
let bossPerson = new Person(boss)
let people = new List<Person>() { bossPerson }.Concat(orderedEmployees)
from person in people
select person).ToList();
If you prefer the lambda syntax:
List<Person> result = BossList
.OrderBy(boss => boss.Name)
.SelectMany(boss => {
IEnumerable<Person> orderedEmployees = boss.Employees.OrderBy(emp => emp.Name);
Person bossPerson = new Person(boss);
return new List<Person>() { bossPerson }.Concat(orderedEmployees);
})
.ToList();

LINQ for a list of list

public class Employee
{
public string Name{get;set;}
public List<Department> Department { get; set; }
public string Company{get;set;}
}
public class Department
{
public string Name { get; set; }
public string Location { get; set; }
}
List<Employee> employees = new List<Employee>();
employees.Add(new Employee() { Company = "Dell", Name = "ABC" });
employees.Add(new Employee() { Company = "Dell", Name = "Aakash" });
employees.Add(new Employee() { Company = "CSC", Name = "Vaibhav" });
employees.Add(new Employee() { Company = "TCS", Name = "Sambhav" });
employees[0].Department = new List<Department>();
employees[0].Department.Add(new Department() { Location = "Delhi", Name = "HR" });
employees[0].Department.Add(new Department() { Location = "Delhi", Name = "Recruitment" });
employees[1].Department = new List<Department>();
employees[1].Department.Add(new Department() { Location = "Noida", Name = "EAO" });
employees[1].Department.Add(new Department() { Location = "Delhi", Name = "Arch" });
employees[2].Department = new List<Department>();
employees[2].Department.Add(new Department() { Location = "Denmark", Name = "Scandi" });
employees[2].Department.Add(new Department() { Location = "Noida", Name = "SAG" });
employees[3].Department = new List<Department>();
employees[3].Department.Add(new Department() { Location = "Mumbai", Name = "NSE" });
I need to write a lambda expression to select all employees where Departement Location is Noida
Use Any extension method:
var results = employees.Where(e => e.Department.Any(d => d.Location == "Noida"))
.ToList();
Actually you even don't need LINQ for that. List<T> has methods FindAll and Exsists which can do the job:
employees.FindAll(e => e.Department.Exists(d => d.Location == "Noida"))

Categories