I'm using the KendoUI in my web application. One of our database tables has an array of values stored in a single column as a varchar
. Everyone has an opinion on this but at the moment I have to work with it.
SQL Server
Office_Ids
1,2,3,4,5
I've been tasked with joining the office names to these ids and also making these ids nicer(styled) within the grid. The problem is that, as a string the are immutable and so it's starting to all get very complicated.
The desired outcome would be the following:
"<OfficeId>1</OfficeId><OfficeName>Some Name</OfficeName><OfficeId>2</OfficeId><OfficeName>Some Name</OfficeName>"
The above outcome also assumes that I join the data to the office table. Usually I would accomplish something like the above using regex if the data was stored in separate tables. That fact it's not is what's causing the confusion.
Here is my controller, this is only a test controller action at the moment as I tried to work this out. You'll see that I do a few things here:
Call my repository to get the data
Create two lists one for the offices and another called
test
for trying to add the above mentioned code items to the strings.I split the array of office Ids from the
Office_Ids
column and return to a listI then iterate over that list and try to use string inserts to pop in those tags
public IQueryable Read() { IQueryable data = _company.GetAll();
List<string> office_item = new List<string>(); List<string> test = new List<string>(); foreach (var item in data) { office_item = item.Office_Ids .Split(',') .Select(x => x.Trim('"')) .Select(x => x.Trim(' ')).ToList(); foreach (var office in office_item ) { client.Insert(0, "<OfficeId>"); client.Insert(2, "</OfficeId>"); test.Add(client); } } Console.WriteLine(test); return data; }
The problems
- This doesn't really work very well
- I'll never know how long an Office Id is, and so if they are ever 4 numbers long, this insert approach will not work.
- I need to return those values to my grid as part of the model which it's not doing at the moment and finally
- I still need to join the office table to these Ids.
The model for CompanyReview
looks like this:
namespace MyCompany.Data
{
public class OfficeReview : BaseEntity
{
public string Office_Ids { get; set; }
}
}
I think I have covered everything here but the TL:DR of this is that I need to separate a string which is an array of values, add some opening and closing tags to it and then return it as part of my model to the grid. After that I'll use some regex to make it look nice.
CodePudding user response:
Consider using XElement
. It lends itself very nicely for XML construction and manipulation using Linq queries.
var officeItems = new List<string> { "1, 2, 42, 12313", "2, 5, 234", "1" };
var officeIdElements = officeItems
.SelectMany(s => s.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries))
.Select(id => new XElement("OfficeId", id));
//The output you requested
string officeIds = string.Concat(officeIdElements.Select(idElement => idElement.ToString()));
However, if you want to expand on this to include other elements, say OfficeName
, then you could do
var officeElements = officeIdElements.Select(idElement =>
{
var officeName = $"Office { idElement.Name }";
var officeNameElement = new XElement("OfficeName", officeName);
return new XElement("Office", idElement, officeNameElement);
});
and if you need to wrap it under a parent node for well-formed XML
var officesElement = new XElement("Offices", officeElements);
/*
<Offices>
<Office>
<OfficeId>1</OfficeId>
<OfficeName>Office OfficeId</OfficeName>
</Office>
<Office>
<OfficeId>2</OfficeId>
<OfficeName>Office OfficeId</OfficeName>
</Office>
<Office>
<OfficeId>42</OfficeId>
<OfficeName>Office OfficeId</OfficeName>
</Office>
<Office>
<OfficeId>12313</OfficeId>
<OfficeName>Office OfficeId</OfficeName>
</Office>
<Office>
<OfficeId>2</OfficeId>
<OfficeName>Office OfficeId</OfficeName>
</Office>
<Office>
<OfficeId>5</OfficeId>
<OfficeName>Office OfficeId</OfficeName>
</Office>
<Office>
<OfficeId>234</OfficeId>
<OfficeName>Office OfficeId</OfficeName>
</Office>
<Office>
<OfficeId>1</OfficeId>
<OfficeName>Office OfficeId</OfficeName>
</Office>
</Offices>
*/
CodePudding user response:
If you have to output a string, the following approach might work:
var officeItems = new List<string> { "1, 2, 42, 12313", "2, 5, 234", "1" };
var officeResults = new List<string>();
foreach (var officeItem in officeItems)
{
foreach (var item in officeItem.Replace(" ", string.Empty).Split(","))
{
var officeName = service.GetOfficeName(item);
officeResults.Add($"<OfficeId>{item}</OfficeId><OfficeName>{officeName}</OfficeName>");
}
}