I have a C# class and data table.
DataTable:
+---------+-----------------+---------------+---------+---------+--------------+
| Pers_Id | Pers_First_Name | Pers_Last_Name| OrderNu | OrderId | Pers_Update |
+---------+-----------------+---------------+---------+---------+--------------+
| 1 | ABC | Ln | 76454 | 1 | 2018-03-25 |
+---------+-----------------+---------------+---------+---------+--------------+
| 1 | ABC | Ln | 76578 | 2 | 2018-03-25 |
+---------+-----------------+---------------+---------+---------+--------------+
Class:
public class Person
{
public int Pers_Id { get; set; }
public string Pers_First_Name { get; set; }
public string Pers_Last_Name { get; set; }
public DateTime Pers_Update { get; set; }
public List<Order> Order_List { get; set; }
public class Order
{
public int OrderID { get; set; }
public string OrderNu { get; set; }
}
}
I need to bind this class from data table and need to convert it into json object for rest API response in asp .net web API.
When i am binding i am getting json duplicate but result should be like this
{
"Pers_Id": 1,
"Pers_First_Name": "ABC",
"Pers_Last_Name": "LN",
"Pers_Update": "",
"Order_List": [
{
"OrderID": "1",
"OrderNu": "76454"
},
{
"OrderID": "2",
"OrderNu": "76578"
}
]
}
When you have an object (f.eks. your Employee object in this example), you should be able to return it like this:
return Content(JsonConvert.SerializeObject(employee), "application/json");
More info here: https://stackoverflow.com/a/34091196/4034346
First;
using System.Web.Script.Serialization;
Second;
If your data table's class isn't same with your Person class, then you should create a new class of datatable version for your persons.
public class Person
{
public int Pers_Id { get; set; }
public string Pers_First_Name { get; set; }
public string Pers_Last_Name { get; set; }
public DateTime Pers_Update { get; set; }
public List<Order> Order_List { get; set; }
public class Order
{
public int OrderID { get; set; }
public int OrderNu { get; set; }
}
}
//You need a class that fits to your DataTable
public class PersonDataTable
{
public int Pers_Id { get; set; }
public string Pers_First_Name { get; set; }
public string Pers_Last_Name { get; set; }
public DateTime Pers_Update { get; set; }
public int OrderId { get; set; }
public int OrderNu { get; set; }
}
In your method;
public string ReturnGoodPeopleJsonFormat()
{
JavaScriptSerializer js = new JavaScriptSerializer();//Needed for converting an object to Json string.
List<PersonDataTable> personDataTableList = new List<PersonDataTable>();//Needed for filling your data from in program or from database
List<Person> personList = new List<Person>();//Needed 'to be converted' in to Json string
//Add items to your DataTable list manually
personDataTableList.Add(
new PersonDataTable { Pers_Id = 1, Pers_First_Name = "ABC", Pers_Last_Name = "Ln", Pers_Update = Convert.ToDateTime("2018-03-25"), OrderId = 1, OrderNu = 76454 });
personDataTableList.Add(
new PersonDataTable { Pers_Id = 1, Pers_First_Name = "ABC", Pers_Last_Name = "Ln", Pers_Update = Convert.ToDateTime("2018-03-25"), OrderId = 2, OrderNu = 76578 });
//or from database
// personDataTableList.AddRange(myDatabaseModel.DataTables.ToList());
//Now group your data by Pers_Id //We are grouping this because we don't want same person 2 or 3 time, we want one person just one time but get all orders in it. That's why we need to group them by Pers_Id
foreach (var personGroup in personDataTableList.GroupBy(x => x.Pers_Id))
{
List<Person.Order> orderList = new List<Person.Order>();
foreach (var dataTablePerson in personDataTableList.Where(x => x.Pers_Id == personGroup.Key))
{
//Get all orders of personGroup one by one in to an Order list from PersonDataTable list by using Pers_Id like a foreign key.
///This personGroup.Key is nothing but Pers_Id\\\
orderList.Add(new Person.Order { OrderID = dataTablePerson.OrderId, OrderNu = dataTablePerson.OrderNu });
}
//Add new Person object to your personList if you don't have it before (by checking Pers_Id)
if (personList.Where(x => x.Pers_Id == personGroup.Key).Count() == 0) //This personGroup.Key is nothing but Pers_Id
{
personList.Add(new Person
{
Pers_Id = personDataTableList.Where(x => x.Pers_Id == personGroup.Key).FirstOrDefault().Pers_Id,
Pers_First_Name = personDataTableList.Where(x => x.Pers_Id == personGroup.Key).FirstOrDefault().Pers_First_Name,
Pers_Last_Name = personDataTableList.Where(x => x.Pers_Id == personGroup.Key).FirstOrDefault().Pers_Last_Name,
Pers_Update = personDataTableList.Where(x => x.Pers_Id == personGroup.Key).FirstOrDefault().Pers_Update,
Order_List = orderList
});
}
}
string JsonString = js.Serialize(personList);
return JsonString;
}
The result is like this:
[{"Pers_Id":1,"Pers_First_Name":"ABC","Pers_Last_Name":"Ln","Pers_Update":"/Date(1521925200000)/","Order_List":[{"OrderID":1,"OrderNu":76454},{"OrderID":2,"OrderNu":76578}]}]
Related
C# MongoDB Driver
public class Details
{
[BsonId]
public ObjectId Id { get; set; }
public string GroupID { get; set; }
public Names[] Name{ get; set; }
}
public class Names
{
public string FullName { get; set; }
public int Age { get; set; }
public int Status {get; set;}
}
Input
var req = [{FullName = "ABC",
Age = 15,
Status = 0}
{FullName = "XYZ",
Age = 16,
Status = 0},
{FullName = "QAZ",
Age = 14,
Status = 0}]
MongoDB Query
var updateDefinationValues = new List<UpdateDefinition<Details>>();
List<FilterDefinition<Details>> listDetailsFilter = new List<FilterDefinition<Details>>();
foreach (var il in req.Names)
{
FilterDefinition<Details> detailsFilter = Builders<Details>.Filter.Where(x => x.GroupID == requestId && x.Names.Any(i => i.FullName == il.FullName));
updateDefinationValues.Add(Builders<Details>.Update.Set(x => x.Names.ElementAt(-1).Status, 1));
listDetailsFilter.Add(detailsFilter);
}
FilterDefinition<Details> filter = Builders<Details>.Filter.Or(test);
var combinedUpdate = Builders<Details>.Update.Combine(updateDefinationValues);
var isUpdated = UpdateOne(_db, filter, combinedUpdate);
The above query is working when listDetailsFilter count == 1.
Error: The positional Operation did not find the match needed for this query
And it is not working when listDetailsFilter count > 1.
There is a hierarchy of four entities (models). All entities have relationships one to many. It's looks following:
public class Region
{
public Guid Id { get; set; }
public int RegionId { get; set; }
public virtual ICollection<District> Districts { get; set; }
}
public class District
{
public Guid Id { get; set; }
public int DistrictId { get; set; }
public virtual ICollection<Building> Buildings { get; set; }
public int RegionId { get; set; }
public Region Region { get; set; }
}
public class Building
{
public Guid Id { get; set; }
public int BuildingId { get; set; }
public int DistrictId { get; set; }
public virtual ICollection<Flat> Flats { get; set; }
public District District { get; set; }
}
public class Flat
{
public Guid Id { get; set; }
public int FlatId { get; set; }
public int BuildingId { get; set; }
public Building Building { get; set; }
}
It is hierarchy like: Region->District->Building->Flat.
I want return collection of Flat thats include all related entities from top.
I do it folowing:
var flat = _context.Flats
.Include(t => t.Building)
.Include(b=>b.Building.District)
.Include(b => b.Building.District.Region).GetPaged(PageNumber, 20);
But for some reason is return breaking result....
[{"id":"6cbb1431-36d4-490c-a047-c211e4db3bdd","flatId":29570,"roomsCount":1,"totalArea":41.95,"kitchenArea":11.85,"floor":21,"buildingId":130,"price":5725650.00,"building":{"id":"03baca1e-02e9-4ee0-ae47-920e3eb0d5bb","buildingId":130,"name":"NNN","queue":1,"housing":"1","districtId":13003,"flats":[
It breaks for some reason on public virtual ICollection<Flat> Flats { get; set; }. I can't remove it becasue it is needed for FK.
The following query works:
_context.Flat
.Join(
_context.Building,
f => f.BuildingId,
b => b.BuildingId,
(f, b) =>
new
{
f = f,
b = b
}
)
.Join(
_context.District,
temp0 => temp0.b.DistrictId,
d => d.DistrictId,
(temp0, d) =>
new
{
temp0 = temp0,
d = d
}
)
.Join(
_context.Region,
temp1 => temp1.d.RegionId,
r => r.RegionId,
(temp1, r) =>
new
{
Id = temp1.temp0.f.Id,
FlatId = temp1.temp0.f.FlatId,
Floor = temp1.temp0.f.Floor,
RoomsCount = temp1.temp0.f.RoomsCount,
TotalArea = temp1.temp0.f.TotalArea,
KitchenArea = temp1.temp0.f.KitchenArea,
Price = temp1.temp0.f.Price,
Building = new
{
Id = temp1.temp0.b.Id,
BuildingId = temp1.temp0.b.Id,
Name = temp1.temp0.b.Name,
Queue = temp1.temp0.b.Queue,
Housing = temp1.temp0.b.Housing,
District = new
{
Id = temp1.d.Id,
DistrictId = temp1.d.DistrictId,
Name = temp1.d.Name,
Regions = new
{
Id = r.Id,
RegionId = r.Id,
Name = r.Name
}
}
}
}
).GetPaged(PageNumber, PageSize)
And it is return what i whant:
{
"id": "a49a0a48-370b-46da-b6da-ea4040cc1431",
"flatId": 84095,
"roomsCount": 3,
"totalArea": 76.5,
"kitchenArea": 11.07,
"floor": 18,
"buildingId": 0,
"price": 5567500,
"building": {
"id": "037c4074-3ff5-4fbd-92ea-88c8f746b883",
"buildingId": 200,
"name": "NNNN",
"queue": 3,
"housing": "4",
"districtId": 0,
"flats": null,
"district": {
"id": "db031e09-1d6c-41f4-9e45-ec6170e3df8b",
"districtId": 5005,
"name": "Distr",
"buildings": null,
"regionId": 0,
"region": {
"id": "5ac5766f-e62e-4da9-86cf-e4a85423503a",
"regionId": 5001,
"name": "Region",
"districts": null
}
}
}
}
But it is looks like cumbersome.
How can I do it using EF features? Or maybe somehow to reduce linq? And why include() return breaking result?
P.S. .GetPaged(PageNumber, 20); is extension method for pagination and he is working fine.
My suggesstion is below
var flag = (from f in _context.Flags
join b in _context.Buildings
on b.BuildingId equals f.BuildingId
join d in _context.Districts
on d.DistrictId equals b.DistrictId
join r in _context.Regions
on r.RegionId equals d.RegionId
select new
{ ...
}).GetPaged(PageNumber, 20);
You can get any property from Building, District and Region to populate to your result object.
I have created 2 models to store the results of an sql query. Now I would like to join them for each of the week's... (week1 = Record_id, week2 = Record_id)
to get a new Object in which I would have all the data from the 1st model, as well as map data from the "Category" Model to it.
I created a new Model for it, but I am not sure how to write a linq query
First Model:
public class CustomData
{
public string full_name { get; set; }
public string location { get; set; }
public int week1 { get; set; }
public int week2 { get; set; }
public int week3 { get; set; }
}
Second Model:
public class Category
{
public int Record_ID { get; set; }
public int Color{ get; set; }
public string Name { get; set; }
}
New Model for end result:
public class WeekView
{
public string full_name { get; set; }
public string location { get; set; }
public Category week1 { get; set; }
public Category week2 { get; set; }
public Category week3 { get; set; }
}
This should work:
List<CustomData> list = new List<CustomData>();
list.Add(new CustomData() { full_name = "test", location = "test", week1 = 0, week2 = 1, week3 = 2 });
list.Add(new CustomData() { full_name = "test2", location = "test2", week1 = 0, week2 = 12, week3 = 22 });
List<Category> categories = new List<Category>();
categories.Add(new Category { Color = 0, Name = "testName", Record_ID = 0 });
categories.Add(new Category { Color = 1, Name = "testName1", Record_ID = 1 });
categories.Add(new Category { Color = 2, Name = "testName2", Record_ID = 2 });
categories.Add(new Category { Color = 3, Name = "testName3", Record_ID = 12 });
categories.Add(new Category { Color = 4, Name = "testName4", Record_ID = 22 });
List<WeekView> results = new List<WeekView>();
results.AddRange(list.Select(x=>
new WeekView() { full_name = x.full_name,
location = x.location,
week1 = categories.FirstOrDefault(c => c.Record_ID == x.week1),
week2 = categories.FirstOrDefault(c => c.Record_ID == x.week2),
week3 = categories.FirstOrDefault(c => c.Record_ID == x.week3)
}));
Try out the following:
var result = (from cd in CustomDatas
join ca1 in Categories on cd.week1 equals ca.Record_ID into ca1r
from ca1 in ca1r.DefaultIfEmpty()
join ca2 in Categories on cd.week2 equals ca.Record_ID into ca2r
from ca2 in ca2r.DefaultIfEmpty()
join ca3 in Categories on cd.week3 equals ca.Record_ID into ca3r
from ca3 in ca3r.DefaultIfEmpty()
select new {
full_name = cd.full_name,
location = cd.location,
week1 = ca1,
week2 = ca2,
week3 = ca3
}
I have a List of Items . The class looks like :
public class DeviceControllerDoorInfo
{
[DataMember]
public string DeviceControllerId { get; set; }
[DataMember]
public string DeviceControllerName { get; set; }
[DataMember]
public string DoorId { get; set; }
[DataMember]
public string DoorName { get; set; }
}
And the data looks like :
DoorId DoorName ControllerId ControllerName
------ -------- ------------ --------------
Door1 DoorOne C1 C1
Door2 DoorTwo C1 C1
Door3 DoorThree C2 C2
I want it to be converted , to look like it.
public class AccessGroupControllerDoorEntity
{
public string ControllerId { get; set; }
public string ControllerName { get; set; }
public List<AccessGroupDoorEnity> Doors { get; set; }
}
public class AccessGroupDoorEnity
{
public string DoorId { get; set; }
public string DoorName { get; set; }
}
Group By the ControllerId and then list the door items.
How to do it ?
I tried :
var controllersId = allDoors.GroupBy(e => e.DeviceControllerId).Select(x => x);
But does it make the Doors as List ?
I am not sure . Please help.
UPDATE
In my Data Service
private AccessGroupEntity ConvertDoorsToEntity(DeviceControllerDoorInfo[] allDoors)
{
// return null if the object is invalid.
if (allDoors != null)
{
AccessGroupEntity entity = new AccessGroupEntity();
entity.ControllerDoorItems = new List<AccessGroupControllerDoorEntity>();
//Convert to requested format instead of the below
foreach (var door in allDoors)
{
entity.DoorItems.Add(new DoorInfoEntity
{
DoorId = door.DoorId,
DoorName = door.DoorName,
ControllerId = door.DeviceControllerId,
ControllerName = door.DeviceControllerName
});
}
return entity;
But instead I want entity.ControllerDoorItems to contain like the below grouped data :
ControllerId -> C1
ControllerName -> C1
Doors -> 2 Objects
DoorId DoorName ControllerId ControllerName
------ -------- ------------ --------------
Door1 DoorOne C1 C1
Door2 DoorTwo C1 C1
Door3 DoorThree C2 C2
When you use GroupBy(e => e.ControllerId) It will Return two lists (for the above example), which the first list has two Items Where ControllerId is C1 and another list with one item that its ControllerId is C2.
So GroupBy returns Lists and not Items.
For your updated question:
List<AccessGroupControllerDoorEntity> grouped = allDoors.GroupBy(e => e.ControllerId)
.Select(group => new AccessGroupControllerDoorEntity
{
DeviceControllerId = group.Key.Id,
DeviceControllerName = group.Key.Name,
Doors = group.ToList()
});
You can try
var list= allDoors.GroupBy(x=>new {x.ControllerId ,Name=ControllerName},
(key, group) => new AccessGroupControllerDoorEntity
{
ControllerId=Key.ControllerId ,
ControllerName=Key.ControllerName,
Doors = group.ToList()
}))
.ToList();
I'm currently experiencing a funny issue here, each time I insert a new item with EntityFramework, I get to see a new Item submitted first before the real time but with the same entries(properties) and a String[] Array in the last column. I actually have a model defined thus
public class SupervisionStageSetupModel
{
public int Id { get; set; }
[Required]
public string StageLevel { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
public IList<SupervisionStageSetupChecklistModel> SupervisionStageSetupChecklists { get; set; }
public string GetAuditDetails(string action)
{
return string.Format("{0} SupervisionStageSetup Setup: {1}", action,Name);
}
}
public class SupervisionStageSetupChecklistModel
{
public int Id { get; set; }
public int SupervisionStageSetupId { get; set; }
public string Description { get; set; }
public string[] Options { get; set; }
}
And in my service, I have a method that does the insert operation as thus
private void ProcessCheckListItems(List<SupervisionStageSetupChecklist> entities,
IList<SupervisionStageSetupChecklistModel> checkListItems, int stageSetupId)
{
var modelIds = checkListItems.Select(x => x.Id).ToList();
var supervisionStageSetupChecklistRepository = _repository.GetRepository<SupervisionStageSetupChecklist>();
var entitiesToDelete =
entities.Where(x => !modelIds.Contains(x.Id));
entitiesToDelete.ForEach(x => supervisionStageSetupChecklistRepository.Delete(x));
var entitiesToAdd = checkListItems.Where(x => x.Id == 0).Select(x =>
new SupervisionStageSetupChecklist()
{
Description = x.Description,
SupervisionStageSetupId = stageSetupId,
Options = String.Join(",",x.Options)
}).ToList();
entitiesToAdd.ForEach(x =>
{
supervisionStageSetupChecklistRepository.Insert(x);
}
);
var entityToUpdate =
entities.Where(x => modelIds.Contains(x.Id));
entityToUpdate.ForEach(source =>
{
var checklistItem = checkListItems.Single(x => x.Id == source.Id);
source.Description = checklistItem.Description;
source.Options = String.Join(",",checklistItem.Options);
supervisionStageSetupChecklistRepository.Update(source);
});
When I put my VS2013 in debug mode to see what's happening, I saw that it was just only the number of items that came from the view that was inserted, but going back to my MSSQL2014 , I found two records inserted as
Id| SupervisionStageId | Description | Options
2 | 3 | Description | String[] Array
3 | 3 | Description | Yes,No
And of course, after setting breakpoint while inserting, I hovered on the entitiesToAdd object which returned 1 as the count, and this not enough, retrieving the item with the following ...
public SupervisionStageSetupItem GetDetails(int id)
{
var entity = _repository.Find(id);
var item = Mapper.Map<SupervisionStageSetup, SupervisionStageSetupItem>(entity);
item.SupervisionStageSetupChecklists =
entity.SupervisionStageSetupChecklists.Where(x => x.SupervisionStageSetupId == entity.Id)
.Select(x => new SupervisionStageSetupChecklistModel()
{
Description = x.Description,Options = x.Options.Split(',')
}).ToList();
return item;
}
I got the one Options property value as "Y","e","s",",","N","o".
I'm perplexed!, Don't know what I'm doing wrong