C# LINQ multiple arrays to simple list of objects - c#

I have an array of objects List<SlovnikWords>, here is the model:
class SlovnikWord
{
public int Id { get; set; } = -1;
public string Title { get; set; }
public string Description { get; set; }
public List<Word> Forms { get; set; }
...
}
And the model for Word is as follows
class Word
{
public int Id { get; set; } = -1;
public string Title { get; set; }
public string Description { get; set; }
...
}
I need to create a list of all the Forms from all the original list of SlovnikWords, here's what I came up with:
var q = SlovnikData.Select(x => x.Forms);
This unfortunately creates an array of arrays, where as I only need one dimensional array of Forms without the outer one, i.e. a compound of x.Forms, please help.

This should do it:
var q = SlovnikData.SelectMany(x => x.Forms);

Related

Deserializing Json to Entity Framework cant convert int to type

I've been trying to deserialize a Json string that contains a list of ints representing colors to then be inserted into a sql database using Entity Framework. I'm pretty new to Entity Framework and read that it doesn't support collections of primitive types, I thought to get around it I could add the class
public class Colors
{
public int Id { get; set; }
public int Color { get; set; }
}
and then create a list in the CharacterColor class to hold the ints
public List<Colors> Colors { get; set; }
However I get the error when trying to deserialize the Json.
Newtonsoft.Json.JsonSerializationException: 'Error converting value
255 to type 'ORAC.Data.Entities.Colors'. Path
'characterColors[0].colors[0]', line 1, position 1200.'
ArgumentException: Could not cast or convert from System.Int64 to ORAC.Data.Entities.Colors.
Would anyone with more experience with Entity Framework be able to see where I'm going wrong.
Character character = JsonConvert.DeserializeObject<Character>(jsonString);
Json string
"{\"packedRecipeType\":\"DynamicCharacterAvatar\",\"name\":\"Character\",\"race\":\"HumanMaleHighPoly\",\"dna\":[{\"dnaType\":\"UMADnaHumanoid\",\"dnaTypeHash\":-212795365,\"packedDna\":\"{\\\"height\\\":128,\\\"headSize\\\":128,\\\"headWidth\\\":93,\\\"neckThickness\\\":108,\\\"armLength\\\":135,\\\"forearmLength\\\":128,\\\"armWidth\\\":116,\\\"forearmWidth\\\":128,\\\"handsSize\\\":118,\\\"feetSize\\\":109,\\\"legSeparation\\\":128,\\\"upperMuscle\\\":129,\\\"lowerMuscle\\\":152,\\\"upperWeight\\\":128,\\\"lowerWeight\\\":81,\\\"legsSize\\\":134,\\\"belly\\\":66,\\\"waist\\\":108,\\\"gluteusSize\\\":38,\\\"earsSize\\\":121,\\\"earsPosition\\\":233,\\\"earsRotation\\\":61,\\\"noseSize\\\":115,\\\"noseCurve\\\":128,\\\"noseWidth\\\":124,\\\"noseInclination\\\":128,\\\"nosePosition\\\":128,\\\"nosePronounced\\\":128,\\\"noseFlatten\\\":118,\\\"chinSize\\\":128,\\\"chinPronounced\\\":128,\\\"chinPosition\\\":128,\\\"mandibleSize\\\":128,\\\"jawsSize\\\":128,\\\"jawsPosition\\\":128,\\\"cheekSize\\\":128,\\\"cheekPosition\\\":128,\\\"lowCheekPronounced\\\":128,\\\"lowCheekPosition\\\":195,\\\"foreheadSize\\\":128,\\\"foreheadPosition\\\":128,\\\"lipsSize\\\":128,\\\"mouthSize\\\":128,\\\"eyeRotation\\\":128,\\\"eyeSize\\\":69,\\\"breastSize\\\":128}\"},{\"dnaType\":\"UMADnaTutorial\",\"dnaTypeHash\":-1679007774,\"packedDna\":\"{\\\"eyeSpacing\\\":128}\"}],\"characterColors\":[{\"name\":\"Skin\",\"colors\":[255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]},{\"name\":\"Hair\",\"colors\":[255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]},{\"name\":\"Eyes\",\"colors\":[255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]},{\"name\":\"Undies\",\"colors\":[255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]}],\"wardrobeSet\":[{\"slot\":\"Underwear\",\"recipe\":\"MaleUnderwear\"}],\"raceAnimatorController\":\"Locomotion\"}"
Entity
public class Character
{
public int UserId { get; set; }
public int CharacterId { get; set; }
public string CharacterName { get; set; }
public string PackedRecipeType { get; set; }
public string Name { get; set; }
public string Race { get; set; }
public List<Dna> Dna { get; set; }
public List<CharacterColor> CharacterColors { get; set; }
public List<WardrobeSet> WardrobeSet { get; set; }
public string RaceAnimatorController { get; set; }
public User User { get; set; }
}
public class Dna
{
public int Id { get; set; }
public string DnaType { get; set; }
public int DnaTypeHash { get; set; }
public string PackedDna { get; set; }
}
public class CharacterColor
{
public int Id { get; set; }
public string Name { get; set; }
public List<Colors> Colors { get; set; }
}
public class WardrobeSet
{
public int Id { get; set; }
public string Slot { get; set; }
public string Recipe { get; set; }
}
public class Colors
{
public int Id { get; set; }
public int Color { get; set; }
}
Solution
I updated the Json and replaced the colors array with a new array of objects
JObject jsonToParse = JObject.Parse(jsonString);
JArray characterColors = (JArray)jsonToParse["characterColors"];
foreach(var item in characterColors)
{
JArray colors = (JArray)item["colors"];
JArray newColorsArray = new JArray();
var i = 0;
foreach (var col in colors)
{
var color = new Color
{
ColorId = i,
Value = (int)col
};
newColorsArray.Add(JToken.FromObject(color));
i++;
}
colors.Replace(newColorsArray);
}
In your Json you have colors defined as an array of ints, not as an object array of your new Colors class. Should be more like colors: [{Id:0, Color:255},{Id:2, Color:255}, .......]
So the JSON is incorrect, in the json the colors array is sent as a List basically
colors: [255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0]
but the .net is expecting something more like the following which is more like a List
colors: [{Id:0, Color:255},{Id:1, Color:255}, ...]
So you can do any of the following:
Change whatever is sending your JSON to send an array of objects of {int, int} instead of an array of ints.
Change your List to be a List and then update all your .net code to adjust to that.
Write a custom Json converter to convert from the json you have to the .net that you have.
You should do 1 or 2, as your data doesn't seem complex enough to go through the effort of 3.

Comparing Arrays LINQ

How can I compare to array in linq and get all elements where there is at least one intersection?
Example:
selectes = {1,5,7}
Bands[0].SongsID {1,9}
Bands[1].SongsID {5,6}
Bands[2].SongsID {4,6}
I need to select Bands[0] and Bands[1].
I tried this:
var selectes2 = Bands.Where(t => t.SongsID.Intersect(selectes));
Bands class:
public class Band
{
public int ID { get; set; }
public string Name { get; set; }
public DateTime YearOfCreate { get; set; }
public string Country { get; set; }
public int[] SongsID { get; set; }
}
var selectes2 = Bands.Where(t => t.SongsID.Intersect(selectes).Any());
Assuming you mean to select any band that has any song ID that matches your list of ids, you could accomplish that with this:
var matchingBands = Bands.Where(band => band.SongsID.Any(selectes.Contains));

Convert flat to hierarchy list?

I have two tables "CategoryGroup" and "Category" which returns data in one list. Requirement is to convert flat list to hierarchy list like CategoryGroup contains related categories.
Please suggest how to convert into hieararchy list?
public class ProfileConditionGroup
{
public Guid ConditionGroupGUID { get; set; }
public string ConditionGroupName { get; set; }
public List<ProfileConditionList> profileConditions { get; set; }
}
public class ProfileConditionList
{
public string ConditionName { get; set; }
public Nullable<Guid> ConditionGUID { get; set; }
public string[] ThisConditionSelectedByProfileIDs { get; set; }
public Nullable<Guid> ParentConditionGroupGUID { get; set; }
public bool IsDefaultSelected { get; set; }
}
This is actually a little tricky without having an actual concrete return type, but here's the way I'd tackle it if you're just building a tree of Guid values.
Given this query:
var query =
from pcg in pcgs
from pcl in pcg.profileConditions
select new
{
pcg.ConditionGroupName,
pcg.ConditionGroupGUID,
pcl.ConditionName,
pcl.ConditionGUID,
pcl.ThisConditionSelectedByProfileIDs,
pcl.ParentConditionGroupGUID,
pcl.IsDefaultSelected,
};
...I'd do this:
var lookup = query.ToLookup(x => x.ParentConditionGroupGUID);
Func<Guid?, Tree<Guid?>> build = null;
build = g =>
{
var r = new Tree<Guid?>() { Value = g };
r.AddRange(lookup[g].Select(x => build(x.ConditionGroupGUID)));
return r;
};
Now you just call build(null) and you should get a tree of Guid?. If you can create you're own output class you'd change the function to Func<Guid?, Tree<YourOutputClass>>.
You need this class for the tree:
public class Tree<T> : List<Tree<T>>
{
public T Value { get; set; }
}

Find a particular element in List<> and fetch whole data of that row if element is found

I have a List<> which contains collection of objects after getting this list of BillSheetDetail I want to find that billWorkDetails[].details_classification =="xyz" and if it is found then fetch all the data of that particular array index of billWorksDetails[] and store it in other array to display.
How can I do this? I am new to C#
public class BillSheetDetail
{
public DateTime creation_date { get; set; }
public string customer_name { get; set; }
public string subject { get; set; }
public decimal tax_rate { get; set; }
public int total_amount { get; set; }
public string special_instruction { get; set; }
public string comment { get; set; }
public List<BillWorkDetail> billWorkDetails { get; set; }
}
[Serializable]
public class BillWorkDetail
{
public string product_name { get; set; }
public decimal quantity { get; set; }
public string unit { get; set; }
public int unit_cost { get; set; }
public int amount { get; set; }
public string remarks { get; set; }
public int row_no { get; set; }
public string details_classifiction { get; set; }
}
You have to combine Enumerable.Where and Any.
List<BillWorkDetail>[] matchingSheetDetails = billSheetDetailList
.Where(sd => sd.billWorkDetails.Any(d => d.details_classifiction == "xyz"))
.Select(sd => sd.billWorkDetails)
.ToArray();
This creates an array of all matching lists. Since your question is unclear, if you actually only want an array of the matching BillWorkDetail objects:
BillWorkDetail[] matchingBillWorkDetails = billSheetDetailList
.SelectMany(sd => sd.billWorkDetails.Where(d => d.details_classifiction == "xyz"))
.ToArray();
SelectMany selects all matching BillWorkDetail out of the List<BillSheetDetail>. Note that both approaches lose the reference to the BillSheetDetail instance from where it came from.
The solution is using the Where clause:
mySheetDetail.billWorkDetails.Where(x => x.details_classification == "xyz").ToList();
Here is a demonstration of the code that is working well: http://ideone.com/s2cUaR
Try this linq method
List<BillWorkDetail> myBillWorkDetails = new Lis<BillWorkDetail>();
myBillWorkDetails = myBillSheetDetail.billWorkDetails.Where(b => b.classifiction == "xyz").ToList();
This code retrieve all BillWorkDetail with classification xyz.

C# Linq search inside object linked property

i'm trying to do some search inside some attributes of my object set but i'm getting some trouble on the right way to mount my linq query, i have my VT_Video class which has its attributes and some linked objects
public partial class VT_Video
{
public int ID { get; set; }
public string title { get; set; }
public string description { get; set; }
public virtual ICollection<VT_VideoTag> VT_VideoTag { get; set; }
}
public partial class VT_VideoTag
{
public int ID { get; set; }
public int tagID { get; set; }
public int videoID { get; set; }
public virtual VT_Tag VT_Tag { get; set; }
public virtual VT_Video VT_Video { get; set; }
}
public partial class VT_Tag
{
public int ID { get; set; }
public string name { get; set; }
public virtual ICollection<VT_VideoTag> VT_VideoTag { get; set; }
}
What i want to accomplish is search a user given word inside my Video collection by VT_Video.title, VT_Video.description and also by VT_Video.VT_VideoTag.VT_Tag.name, what i managed to do so far is only search the title and description:
var myVideos = db.VT_Video.Include("VT_VideoTag")
.Include("VT_VideoTag.VT_Tag")
.Where(vid =>
vid.descricao.Contains(strBusca) ||
vid.titulo.Contains(strBusca)).ToList();
Now, i know i can do what i want with some foreach and extra code but i wondered if it would be possible to do it using linq and also keep my code clean.
Thanks.
I have not worked with LINQ to SQL much, but it seems like .Any() would satisfy your requirement:
var myVideos = db.VT_Video.Include("VT_VideoTag")
.Include("VT_VideoTag.VT_Tag")
.Where(vid =>
vid.descricao.Contains(strBusca) ||
vid.titulo.Contains(strBusca) ||
vid.VT_VideoTag.Any(tag => tag.name.Contains(strBusca))).ToList();
Notice I added this clause:
vid.VT_VideoTag.Any(tag => tag.name.Contains(strBusca))
Which returns true if any tag in the collection has a name that contains your search string.

Categories

Resources