I have list of objects "orginalobject" is like below and also figure . This is populated from database
orginalobject.monitorName
orginalobject.ProcessGUID
orginalobject.Apikey
orginalobject.AIRSTATION
orginalobject.variableName
orginalobject.id
orginalobject.AIRSTATIONChannel
As in Attached image you can see some columns are repeated that is
monitorName
ProcessGUID
Apikey
AIRSTATION
And non repeatable columns are
variableName
id
AIRSTATIONChannel
so I want list should be grouped by these repeating columns and other columns should become list of this object using lamda or linq
object.monitorName
object.ProcessGUID
object.Apikey
object.AIRSTATION
Object.List<Subobjects> list
And Subobjects class will be like
ObjectSubobjects.variableName
ObjectSubobjects.id
ObjectSubobjects.AIRSTATIONChannel
If I understand you question correctly, you just want to group list of objects by their non-unique monitorName, ProcessGUID, Apikey and AIRSTATION properties used as a key and for each of these groups create list of sub-objects with the remaining unique properties?
This can be done with the following simple linq query. First it uses GroupBy to create groups of originalobjects with the same values of non-unique properties. I used ValueTuple struct to represent combination of non-unique properties as a single object used as a key for grouping. But from provided image it seems that it might be superfluous and that any of the non-unique properties alone used as a grouping key should be sufficient. The rest of the query contains just two projections (Select) that copies values from originalobjects to newly created GroupObjects and ObjectSubobjects.
var groupedObjects = objects.GroupBy(o => (o.monitorName, o.ProcessGUID, o.Apikey, o.AIRSTATION))
.Select(g => new GroupObject()
{
monitorName = g.Key.monitorName,
ProcessGUID = g.Key.ProcessGUID,
Apikey = g.Key.Apikey,
AIRSTATION = g.Key.AIRSTATION,
list = g.Select(s => new ObjectSubobjects()
{
variableName = s.variableName,
id = s.id,
AIRSTATIONChannel = s.AIRSTATIONChannel
})
.ToList()
})
.ToList();
public class orginalobject
{
public string monitorName { get; set; }
public Guid ProcessGUID { get; set; }
public Guid Apikey { get; set; }
public string AIRSTATION { get; set; }
public string variableName { get; set; }
public Guid id { get; set; }
public int AIRSTATIONChannel { get; set; }
}
public class GroupObject
{
public string monitorName { get; set; }
public Guid ProcessGUID { get; set; }
public Guid Apikey { get; set; }
public string AIRSTATION { get; set; }
public List<ObjectSubobjects> list { get; set; }
}
public class ObjectSubobjects
{
public string variableName { get; set; }
public Guid id { get; set; }
public int AIRSTATIONChannel { get; set; }
}
Related
I would like to filter my 'TranslationSet' entities, based on their 'Translations' Collection Navigation Property.
E.g.
If a 'Translation' has a 'LanguageId' of 5 (Italian), then the 'TranslationSet' that contains this 'Translation' should be removed from the result.
Here are my Entity classes:
public class Language
{
public int LanguageId { get; set; }
public string NationalLanguage { get; set; }
//Make table multi tenanted.
public int TenantId { get; set; }
public ApplicationTenant Tenant { get; set; }
public List<Translation> Translation { get; set; } = new List<Translation>();
}
public class Translation
{
public int TranslationId { get; set; }
public string TranslatedText { get; set; }
public int LanguageId { get; set; }
public Language Language { get; set; }
//Make table multi tenanted.
public int TenantId { get; set; }
public ApplicationTenant Tenant { get; set; }
public int TranslationSetId { get; set; }
public TranslationSet TranslationSet {get; set;}
}
public class TranslationSet
{
public int TranslationSetId { get; set; }
public int TenantId { get; set; }
public ApplicationTenant Tenant { get; set; }
public IEnumerable<Translation> Translations { get; set; }
}
Here is my attempt
From the image you can see that the query fails because a Translation exists with LanguageId of 5.
I have tried many many attempts to resolve this but I can't even get close the LINQ which returns my query correctly.
Please let me know if any further clarification is needed and thanks in advance to anybody who offers help.
My rule of the thumb that nearly always work is: start by querying the entities you want. That will prevent duplicates as you see in your query result. Then add predicates to filter the entities, using navigation properties. That will be:
var sets = TranslationSets // start the query here
.Where(ts => ts.Translations.All(t => t.LanguageId != 5)); // Filter
Or if you like this better:
var sets = TranslationSets // start the query here
.Where(ts => !ts.Translations.Any(t => t.LanguageId == 5)); // Filter
EF will translate both queries as WHERE NOT EXISTS.
I have an order object with its partial class containing changes history:
public class SomeOrder
{
public string SomeOrderNumber { get; set; }
public string Status { get; set; }
public IEnumerable<SomeOrderChangesHistory> ChangesHistory { get; set; }
}
public partial class SomeOrderChangesHistory
{
public string PropertyName { get; set; }
public string OldValue { get; set; }
public string NewValue { get; set; }
public DateTime DateTimeUtc { get; set; }
public string UserName { get; set; }
}
I'll be getting a list of SomeOrder and I want to filter out the orders if they are updated by api user.
The orders updated by api user will have one or more SomeOrderChangesHistory object in the ChangesHistory list with api user value in the UserName property (in SomeOrderChangesHistory object).
How do I accomplish this?
Based on #NetMage's excellent comment:
var ordersNotUpdatedByAPIUser = orders
.Where(o => !o.ChangeHistory.Any(ch => ch.UserName == "api user"))
.ToList()
It will filter out all the orders updated by api user which is exactly what I want.
I have table in a database that stores the following objects:
public class MyObjInfoWebView
{
public string SerialNumber { get; set; }
public string ProductCode { get; set; }
public string Description { get; set; }
public string Certificate { get; set; }
public string Language { get; set; }
}
I also have a list of serial numbers, for example this:
var list = new List<string> {"010719/522", "010719/523", "010719/524", "010719/525", "010719/526"}
Is it possible to write (and how) LINQ query to filter objects from the table according to the available list of serial numbers and the required language?
This request solved my problem
_contex.InfoWeb.Where(x => list.Contains(x.SerialNumber) && x.Language == lang).ToListAsync();
I'm trying to get the count of a dictionary's value collection, where a field of the collection item, matches the key in the collection, as well as the type.
So my collection looks like this, note the object is initialized, this is just pseudo code:
var results = Dictionary<string, List<CourseEnrollmentsByStudentSQLResult>();
Now the CourseEnrollmentsByStudentSQLResult is a data transfer object, that maps to the rows returned from my query.
public class CourseEnrollmentsByStudentSQLResult
{
public int StudentID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string College { get; set; }
public int CollegeId { get; set; }
public string Prefix { get; set; }
public string CourseNumber { get; set; }
public string Course { get; set; }
public int CourseId { get; set; }
public string Program { get; set; }
public string Term { get; set; }
public string Status { get; set; }
public List<StudentCoursesSQLResult> Courses { get; set; }
}
You will notice that my CourseEnrollmentsByStudentSQLResult class also has a collection of StudentCoursesSQLResult objects. This is the list I'm trying to get a count of, based on two conditions.
First that the course, which is the string KEY in the dictionary, matches the course of the StudentCoursesSQLResult and then I need to filter on the StudentCoursesSQLResult.Type.
Here is the StudentCoursesSQLResult class:
public class StudentCoursesSQLResult
{
public int StudentID { get; set; }
public int Position { get; set; }
public string Prefix { get; set; }
public string CourseNumber { get; set; }
public string Course { get; set; }
public string Type { get; set; }
}
Now to get the count I'm looping over my dictionary and outputting headers for each key, this is where I'm trying to output the count for the dictionary's value collection.
foreach(var result in results) {
<span class="label label-default label-fat">
#result.Value.SelectMany(r => r.Courses).Count(c => c.Course == result.Key && c.Type == "required")
</span>
}
But for some reason it's returning zero, when I know it shouldn't be.
Can someone please point me in the right direction? Everything I've found so far online has said to use SelectMany, but I'm not having any luck.
Here is a screenshot of the debug output for a single course for the dictionary's value collection, where the Type is "required".
Looking at your screen shot, "Advanced French I: Structure and Expression" doesn't match the key of "Medieval Art and Architecture", which explains the incorrect count.
Instead, filter the CourseEnrollmentsByStudentSQLResult collection to those matching the dictionary key, then select all courses in those matched records, and finally count the courses that are "required".
#result.Value.Where(r => r.Course == result.Key)
.SelectMany(r => r.Courses)
.Count(c => c.Type == "required");
A variation on vivat if you want to do this in a program:
var cnt = selections.Where(r => r.Key == "Items").SelectMany(r => r.Value).Count();
"Items" is the Key value within the collection. In my case I created this collection:
Dictionary<string, string[]> selections = new Dictionary<string, string[]>();
Then added a simple set of values based on a key:
selections.Add("Items", txtItems.Text.Replace("\n", "").Split('\r'));
Later on I wanted to check if there had been any values set so I used the above method to count. It works great and in initial testing it helped me discover I needed to cleanup text entries before setting them up.
Let's say I have 2 entities (1-to-many) relation: Component and Part like so:
public Component
{
string CompName { get; set; }
byte[] CompBlob { get; set; }
ICollection<Part> Parts { get; set; }
}
public Part
{
string PartName { get; set; }
byte[] PartBlob { get; set; }
}
When I load a Component, I want to always load its Parts for this particular entity.
I want to know how to select / project a list of components so that EF will not load additional inner properties (eg: only CompName and PartName to be loaded but not CompBlob and inner PartBlob).
Maybe something like below, but how to apply a selector for Parts?
//
dbContext.Components.Include(c => c.Parts).Where(filterComponents).Select(.?.)
//
If needed, I have LazyLoadingEnabled set to false
If you're using entity framework, you need to add primary key for each entity, like below:
public class Component
{
public int Id { get; set; }
public string CompName { get; set; }
public byte[] CompBlob { get; set; }
public ICollection<Part> Parts { get; set; }
}
public class Part
{
public int Id { get; set; }
public string PartName { get; set; }
public byte[] PartBlob { get; set; }
}
Then make the query like:
LazyLoading Disable Case:
var result = dbContext.Components.Include("Parts").Select(m => new
{m.CompName, PartNames = m.Parts.Select(n => n.PartName)}).ToList();
LazyLoading Enabled Case:
var result = dbContext.Components.Select(m => new
{m.CompName, PartNames = m.Parts.Select(n => n.PartName)}).ToList();
If I understand you correctly...
var query = dbContext.Components.Select(x => new {
CompName = x.CompName,
Parts = x.Parts.Select(p => p.PartName)
}).ToList();
Add additional filters and selectors as you require. You may / may not need the Include statement (.Include("Parts"))