Why OrderBy does not sort the data? - c#

I want to group and sort data, but OrderBy function is not working as it should, and I'm wondering what I'm doing wrong
Code:
var data = new List<PreparedData>() {
new PreparedData {
IsGroup = false,
Service = "Number 5",
Name = "Banana",
SomeValue = 5,
},
new PreparedData {
IsGroup = false,
Service = "Number 5",
Name = "Apple",
SomeValue = 5,
},
new PreparedData {
IsGroup = false,
Service = "Number 3",
Name = "Apple",
SomeValue = 5,
},
new PreparedData {
IsGroup = false,
Service = "Number 3",
Name = "Blueberry",
SomeValue = 9,
},
new PreparedData {
IsGroup = true,
Service = "Number 9",
Name = "Garlic",
SomeValue = 7,
}
}
var groupedAndSortedData = data.GroupBy(x => x.IsGroup).Select(isGroup => new FruitViewData
{
IsGroup = isGroup.Key,
FruitData = isGroup.GroupBy(s => s.Service).Select(service => new FruitServiceData
{
Service = service.OrderBy(z => z.Service).First().Service,
FruitTypeData = service.OrderBy(x => x.Name).Select(fruitType => new FruitTypeData
{
Name = fruitType.Name,
SomeValue = fruitType.SomeValue
}
}
}
At the end I get:
[
{
IsGroup: false
FruitData: [
{
Service: "Number 5",
FruitTypeData: [
{
Name: "Banana",
SomeValue = 5,
},
{
Name: "Apple",
SomeValue = 5,
},
]
},
{
Service: "Number 3",
FruitTypeData: [
{
Name: "Apple",
SomeValue = 5,
},
{
Name: "Blueberry",
SomeValue = 9,
},
]
]
},
{
IsGroup: true
FruitData: [
{
Service: "Number 9",
FruitTypeData: [
{
Name: "Garlic",
SomeValue = 9,
}
]
},
]
},
]
But I would like to get sorted data like:
[
{
IsGroup: false
FruitData: [
{
Service: "Number 3",
FruitTypeData: [
{
Name: "Apple",
SomeValue = 5,
},
{
Name: "Blueberry",
SomeValue = 9,
},
]
},
{
Service: "Number 5",
FruitTypeData: [
{
Name: "Apple",
SomeValue = 5,
},
{
Name: "Banana",
SomeValue = 5,
},
]
},
]
},
{
IsGroup: true
FruitData: [
{
Service: "Number 9",
FruitTypeData: [
{
Name: "Garlic",
SomeValue = 9,
}
]
},
]
},
]
I tried to sort it in a different way like for example using the foreach loop after groupedAndSortedData and add OrderBy function to every iteration but also without satisfactory effect
What should I change to get the expected result?

It looks to me like you need to order the FruitData results:
var groupedAndSortedData = data.GroupBy(x => x.IsGroup).Select(isGroup => new FruitViewData
{
IsGroup = isGroup.Key,
FruitData = isGroup.GroupBy(s => s.Service).Select(service => new FruitServiceData
{
Service = service.OrderBy(z => z.Service).First().Service,
FruitTypeData = service.OrderBy(x => x.Name).Select(fruitType => new FruitTypeData
{
Name = fruitType.Name,
SomeValue = fruitType.SomeValue
})
}).OrderBy(fd => fd.Service) //This here
});
Notice the .OrderBy(fd => fd.Service) method call.

Related

How to test is an "If loop" in UnitTestcase Xunit C#

I have a Rest API endpoint. And I want to check if the loop is executing in the Unit test case Following is my code. But if (days > 365) part I not covered in my unit test case. how to include that part in the unit test case
[HttpPost, Route("v1/test")]
public async Task<IActionResult> Run(Request request)
{
var days = (request.ToDate - request.FromDate).TotalDays;
var today = new MonthMap(request.ToDate.UtcDateTime.Month, request.ToDate.UtcDateTime.Day);
var fromDay = new MonthMap(request.FromDate.UtcDateTime.Month, request.FromDate.UtcDateTime.Day);
if (days > 365)
{
fromDay = new MonthMap(1, 1);
today = new MonthMap(12, 31);
}
var query = new Query
{
ToDay = today,
FromDay = fromDay
};
var today = DateTimeOffset.UtcNow;
var results = await _valueService.GetResult(query, today);
return new OkObjectResult(results);
}
}
public MonthMap(int month, int day)
{
if (month > 12 || month < 1)
{
throw new ArgumentException(" number between 1 and 12");
}
if (day < 1 || day > 31)
{
throw new ArgumentException("number between 1 and 31");
}
Day = day;
Month = month;
Unittest
[Fact]
public async Task Test_Run_When_Day_Greater_Than_365()
{
// Arrange
var request = new Request
{
FromDate = new DateTimeOffset(2022, 1, 1, 0, 0, 0, TimeSpan.Zero),
ToDate = new DateTimeOffset(2022, 12, 31, 0, 0, 0, TimeSpan.Zero),
};
var mockValueService = new Mock<IValueService>();
var mockLogger = new Mock<ILogger<ReportsController>>();
var controller = new ReportsController(mockValueService .Object, mockLogger.Object);
mockValueService .Setup(x => x.GetResult(It.IsAny<Query>(),It.IsAny<DateTimeOffset>()))
.ReturnsAsync(new List<MonthLyDataModel>
{new IresultModel{ Id = "1", Result= "CO1", Month= "1" },
{new IresultModel{ Id = "1", Result= "CO1", Month= "2" },
{new IresultModel{ Id = "1", Result= "CO1", Month= "3" },
{new IresultModel{ Id = "1", Result= "CO1", Month= "4" },
{new IresultModel{ Id = "1", Result= "CO1", Month= "5" },
{new IresultModel{ Id = "1", Result= "CO1", Month= "6" },
{new IresultModel{ Id = "1", Result= "CO1", Month= "7" },
{new IresultModel{ Id = "1", Result= "CO1", Month= "8" },
{new IresultModel{ Id = "1", Result= "CO1", Month= "9" },
{new IresultModel{ Id = "1", Result= "CO1", Month= "10" },
{new IresultModel{ Id = "1", Result= "CO1", Month= "11" },
{new IresultModel{ Id = "1", Result= "CO1", Month= "12" },
});
// Act
var result = await controller. Run(request);
Assert.IsType<OkObjectResult>(result);
var resultObject = (OkObjectResult)result;
var resultJson = (List<MonthLyDataModel>)resultObject.Value;
Assert.Equal(resultJson.Count, 12);
}
My unit test is not actually covered the loop. Its just counting only the dummy data. Is it possible to check this part of code?. If yes, how to do that?

Net Core API not returning all children DB First

Below is my code. I'm wondering if I might be better off using something else. I feel like this should be a fairly simple return.
Repository:
public Task<OrderHistory> GetInvoicedMacolaOrder(string orderNumber)
{
orderNumber = " " + orderNumber;
DataContext.ChangeTracker.LazyLoadingEnabled = false;
var order = DataContext.OrderHistory
.Include(order => order.OrderLines)
.ThenInclude(line => line.vw_uniqueCartonIds)
.FirstOrDefaultAsync(o => o.ord_no == orderNumber);
return order;
}
OrderHistoryController:
[Authorize(Policy = "CreateReplacementOrder")]
[HttpGet("invoicedorder/{orderNumber}/get")]
public async Task<IActionResult> OrderLookUp(string orderNumber)
{
if (PoExists(orderNumber))
{
var order = await _mrepo.GetInvoicedOrder(orderNumber);
var orderToReturn = _mapper.Map<OrderHistoryDtoDetail>(order);
return Ok(orderToReturn);
}
else
{
return BadRequest("Could not find order number.");
}
}
This is what returns:
{
"ord_no": "51464326",
"status": "P",
"ord_dt": "2020-03-29T00:00:00",
"apply_to_no": null,
"oe_po_no": "3804339 ",
"cus_no": "65564654018",
"ship_to_name": "Omar Brown"
"OrderLines": [
{
"ord_type": "O",
"ord_no": "51464326",
"line_seq_no": 1,
"item_no": "jkhhuk",
"line_no": 1,
"vw_uniqueCartonIds": [
{
"box_id": 20,
"prod_cat": "044",
"box_number": 1,
"uniqueBoxID": "100001"
},
{
"box_id": 20,
"prod_cat": "044",
"box_number": 2,
"uniqueBoxID": "100002"
},
{
"box_id": 20,
"prod_cat": "044",
"box_number": 3,
"uniqueBoxID": "100003"
}
]
}
]
}
What I'm expecting:
{
"ord_no": "51464326",
"status": "P",
"ord_dt": "2020-03-29T00:00:00",
"apply_to_no": null,
"oe_po_no": "3804339 ",
"cus_no": "65564654018",
"ship_to_name": "Omar Brown"
"OrderLines": [
{
"ord_type": "O",
"ord_no": "51464326",
"line_seq_no": 1,
"item_no": "jkhhuk",
"line_no": 1,
"vw_uniqueCartonIds": [
{
"box_id": 20,
"prod_cat": "044",
"box_number": 1,
"uniqueBoxID": "100001"
},
{
"box_id": 21,
"prod_cat": "044",
"box_number": 2,
"uniqueBoxID": "100002"
},
{
"box_id": 22,
"prod_cat": "044",
"box_number": 3,
"uniqueBoxID": "100003"
}
]
},
{
"ord_type": "O",
"ord_no": "51464326",
"line_seq_no": 2,
"item_no": "58hhuk",
"line_no": 2,
"vw_uniqueCartonIds": [
{
"box_id": 25,
"prod_cat": "054",
"box_number": 1,
"uniqueBoxID": "200001"
},
{
"box_id": 26,
"prod_cat": "054",
"box_number": 2,
"uniqueBoxID": "200002"
}
]
}
]
}
Also I have seen the posts about ReferenceLoopHandling and added that to my startup.cs file,but to no avail.
services.AddControllers(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
})
.AddNewtonsoftJson(opt =>
{
opt.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
What causes the problem?

How to put lists together into json in C#?

I have this code here in C# (just a sample):
var list1 = ( from x
join y
select new
{
id, name
});
var counta = list1.count;
if (counta > 0)
{
for (var i = 0; i < counta; i++)
{
var userid = list1[i].id;
var user = user.Where(a => a.id == user).Select(a => a.userid).FirstOrDefault();
var list2 = (
from f
join g.Where(a => a.userid = user)select new
{
hourId, hourName
}
);
if (list2 > 0)
{
foreach (var product in list2)
{
var list3 = (
from p.
where (a => a.id == user)join q.
where (a => a.id == user)select new
{
productId, productName
});
}
}
}
}
Here is list1,list2,list3 relationship: list1 has many list2, list2 has many list3 and here is the JSON that I expected to return:
[
{
"list1": {
"id": 1,
"name": "Adam",
"list2": [
{
"hourId": 1,
"hourName": "08:00",
"list3": [
{
"productId": 1,
"productName": "Candy"
},
{
"productId": 2,
"productName": "Cookie"
}
]
},
{
"hourId": 2,
"hourName": "09:00",
"list3": [
{
"productId": 1,
"productName": "Candy"
},
{
"productId": 2,
"productName": "Cookie"
}
]
}
]
}
}
]
So my question here is how can I put list1, list2, list3 together to return the below JSON? Do I have to join 3 lists in LINQ again?
Thank you!

C# + EntityFramework: Convert multiple group by query to nested JSON

I made the following linq statement
C#
var list = from row in repository.GetAllEntities()
group row by new { row.RegionString, row.SubRegionString, row.CountryString } into g
select new { g.Key.RegionString, g.Key.SubRegionString, g.Key.CountryString, Count = g.Count() };
return Json(list, JsonRequestBehavior.AllowGet);
That returns
[
{
"RegionString":"Americas",
"SubRegionString":"",
"CountryString":"",
"Count":2
},
{
"RegionString":"Americas",
"SubRegionString":"NorthAmerica",
"CountryString":"Canada",
"Count":5
},
{
"RegionString":"Americas",
"SubRegionString":"NorthAmerica",
"CountryString":"US",
"Count":3
},
{
"RegionString":"Americas",
"SubRegionString":"SouthAmerica",
"CountryString":"Chile",
"Count":3
},
{
"RegionString":"EMEA",
"SubRegionString":"AsiaPacific",
"CountryString":"Australia",
"Count":2
},
{
"RegionString":"EMEA",
"SubRegionString":"AsiaPacific",
"CountryString":"Japan",
"Count":1
},
{
"RegionString":"EMEA",
"SubRegionString":"SouthernEurope",
"CountryString":"Turkey",
"Count":1
},
{
"RegionString":"EMEA",
"SubRegionString":"WesternEurope",
"CountryString":"",
"Count":1
}
]
But I am trying to make it into this format
[{
name: "Americas",
children: [
{
name: "NorthAmerica",
children: [{ "name": "Canada", "count": 5 },
{ "name": "US", "count": 3 }]
},
{
name: "SouthAmerica",
children: [{ "name": "Chile", "count": 1 }]
},
],
},
{
name: "EMA",
children: [
{
name: "AsiaPacific",
children: [{ "name": "Australia", "count": 2 },
{ "name": "Japan", "count": 1 }]
},
{
name: "SouthernEurope",
children: [{ "name": "Turkey", "count": 1 }]
},
],
}]
How could I modify the statement to get the result I'm looking for? Non linq answers are acceptable too.
EDIT: Region is the parent of SubRegion, SubRegion is the parent of Country and Count is the unique number of items that belongs to Country
Here is the linq query you want (I've removed the -String postfix for readability):
var list =
from entity in repository.GetAllEntities()
group entity by entity.Region into regions
let childrenOfRegions =
from region in regions
group region by region.SubRegion into subregions
let countriesOfSubRegions =
from subregion in subregions
group subregion by subregion.Country into countries
select new { Name = countries.Key }
select new { Name = subregions.Key, Children = countriesOfSubRegions }
select new { Name = regions.Key, Children = childrenOfRegions };
There is no Count in this query, since I don't really understand what you are counting.
What I'm doing here is grouping the rows into Regions and in the last line you can see the
select new { Name = regions.Key, ... } part where I'm returning the Regions.
To get the children, you need to group the Regions into SubRegions (the same way with Regions). You repeat this all the way down to the Countries and you're done.

what is the best way to generate json from C#

i am trying to mimic an example where they are using hard coded JSON
{
"page": 1,
"total": 1,
"records": 2,
"rows": [
{"id": 1, "cell": ["1", "Super Item", "300", 0, null, false, false]},
{"id": 2, "cell": ["2", "Item 1", "100", 1, 1, false, false]},
{"id": 3, "cell": ["3", "Sub Item 1", "50", 2, 2, true, true]},
{"id": 4, "cell": ["4", "Sub Item 2", "25", 2, 2, false, false]},
{"id": 5, "cell": ["5", "Sub-sub Item 1", "25", 3, 4, true, true]},
{"id": 6, "cell": ["6", "Sub Item 3", "25", 2, 2, true, true]},
{"id": 7, "cell": ["7", "Item 2", "200", 1, 1, false, false]},
{"id": 8, "cell": ["8", "Sub Item 1", "100", 2, 7, false, false]},
{"id": 9, "cell": ["9", "Sub-sub Item 1", "50", 3, 8, true, true]},
{"id": 10, "cell": ["10", "Sub-sub Item 2", "50", 3, 8, true, true]},
{"id": 11, "cell": ["11", "Sub Item 2", "100", 2, 7, true, true]}
]
}
but i need to generate this from C#. Are there any suggestions for the best way to go about generating this above in C#?
The Controller class has a Json method that serialises objects as JSON, so in your action method you just create the object and call the method:
public ActionResult GetData() {
return Json(
new {
page = 1,
total = 1,
records = 2,
rows = new[] {
new { id = 1, cell = new object[] { "1", "Super Item", "300", 0, null, false, false } },
new { id = 2, cell = new object[] { "2", "Item 1", "100", 1, 1, false, false } },
new { id = 3, cell = new object[] { "3", "Sub Item 1", "50", 2, 2, true, true } },
new { id = 4, cell = new object[] { "4", "Sub Item 2", "25", 2, 2, false, false } },
new { id = 5, cell = new object[] { "5", "Sub-sub Item 1", "25", 3, 4, true, true } },
new { id = 6, cell = new object[] { "6", "Sub Item 3", "25", 2, 2, true, true } },
new { id = 7, cell = new object[] { "7", "Item 2", "200", 1, 1, false, false } },
new { id = 8, cell = new object[] { "8", "Sub Item 1", "100", 2, 7, false, false } },
new { id = 9, cell = new object[] { "9", "Sub-sub Item 1", "50", 3, 8, true, true } },
new { id = 10, cell = new object[] { "10", "Sub-sub Item 2", "50", 3, 8, true, true } },
new { id = 11, cell = new object[] { "11", "Sub Item 2", "100", 2, 7, true, true } }
}
}
);
}
There's a class built into .Net 2+ which is called 'JavaScriptSerializer' which creates a JSON structured string based on a .Net typed class.
Using the serializer you can simply created a class with properties and collections to represent your JSON data. Create an instance of it in .Net server side code and then respond using the serializer to generate a valid JSON string response.
Here's an example of converting a Person class instance to a serialized JSON string;
JavaScriptSerializer js = new JavaScriptSerializer();
Person p1 = new Person();
p1.firstName = "Brian";
p1.lastName = "Scott";
p1.department = "Microsoft";
p1.address.addressline1 = "Microsoft";
p1.address.addressline2 = "";
p1.address.city = "Redmond";
p1.address.state = "Seattle";
p1.address.country = "America";
p1.address.pin = 560028;
p1.technologies = new string[] { "IIS", "ASP.NET", "JavaScript", "AJAX" };
string strJSON = js.Serialize(p1);
This will produce a valid JSON string of
{"firstName":"Brian","lastName":"Scott","department":"Microsoft","address":{"addressline1":"Microsoft","addressline2":"","city":"Redmond","state":"Seattle","country":"America","pin":560028},"technologies":["IIS","ASP.NET","JavaScript","AJAX"]}
If you are intending to use a webservice to produce the JSON response to the client side then you can mark your method as;
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string GetPersonJSON()
{
JavaScriptSerializer js = new JavaScriptSerializer();
Person p1 = new Person();
p1.firstName = "Brian";
p1.lastName = "Scott";
p1.department = "Microsoft";
p1.address.addressline1 = "Microsoft";
p1.address.addressline2 = "";
p1.address.city = "Redmond";
p1.address.state = "Seattle";
p1.address.country = "America";
p1.address.pin = 560028;
p1.technologies = new string[] { "IIS", "ASP.NET", "JavaScript", "AJAX" };
return js.Serialize(p1);
}
Apparently you are trying to populate a jqGrid and you're using ASP.NET MVC.
If you have defined a class for these values:
["1", "Super Item", "300", 0, null, false, false]
You can store all the elements in a collection myCollection
you can do something like this:
var ReturnData = new
{
total = totalPages,
page = page,
records = totalRecords,
rows = myCollection.Select(r => new
{
id = r.Id.ToString(),
cell = new String[] { r.Field1, r.Field2, r.Field3, r.Field4 }
})
};
return (Json(ReturnData, JsonRequestBehavior.DenyGet));
class Row {
public int id {get;set;}
public object[] cell {get;set;}
}
class Data {
public int page {get;set;}
public int total {get;set;}
public int records {get;set;}
public Row[] rows {get;set;}
}
var myData = new Data(){ .... };
var json = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(myData);

Categories

Resources