now I can not get the correct information
List<HeaderHelper> h = pr.Actual_View();
foreach (TemplateHeader t in pr.TemplateView())
{
var v= h.Where(z => z.Country == t.Pais
&& z.dia == t.diaTotal
&& z.Segment == t.Segmento).FirstOrDefault();
}
The
pr.Actual_View()
is a class method for a list containing the following fields:
Country (string)
dia (int)
Segment (string)
The
pr.TemplateView()
is a class method for list containing the same fields and same datatype
the list t may contain more information than the list h, so I need to filter the list h with several criteria, but when I run the code does not correctly filter the list, returning a null.
If v is null, that suggests that none of the values in t matched your Where clause, so FirstOrDefault returned the default value of TemplateHeader, which is null.
Without more information or sample data we've got absolutely no way of knowing why none of the values in t matched, but that's what the null value of v indicates.
Related
Hey I have a object being grouped to get a number of queries. For one of the properties SchoolInfoType I want to get list of all the distinct properties typeValues (property of SchoolInfoType) where typeName (property of schoolInfoType) = recess in a string list, but I can't seem to get it to work. School Info type may also be null so I also need to do a null check on properties. Final return type I want is List.
What I have so far, seems to be making a double enumerable, when I really only want 1.
Example code
var data = session.GroupBy(x => x.SchoolId).Select( a => new SchoolObject {
StudentHours = a.Sum(m => m.Hours),
// Query I tried but doesnt return correct return type end up getting embedded enumerables
// need the null check to prevent exception on comparing on null type, end result should
be list of unique type values matching where conditions
Types = a.Where( x => x.SchoolInfoType != null)
.Select( t => t.SchoolInfoType.Where(d => d.typeName == "recess")
.Select(n => n.TypeValue).Distinct))
}).ToList();
Structure of School Info Type Object relevant info
public class SchoolInfoType {
public string TypeName {get; set; }
public string TypeValue {get; set; }
}
The internal select is what is causing the nested output
Types = a.Where(x => x.SchoolInfoType != null)
.Select(x => x.SchoolInfoType)
.Where(x => x.typeName == "recess")
.Select(n => n.TypeValue)
.Distinct()
.ToList();
Your query is asking for IEnumerable of TypeValue's that is distinct and == recess, filtered from an IEnumerable that was filtered on nulls. This sort of nesting is unclear and is the cause of the end result being a nested IEnumerable. You are selecting within a select
A Select is going to produce you an IEnumerable, so selecting within another select is going to get you nesting. Not to mention the time and space complexity is going to suffer when it steps down the IL to nested loops
I have a list 'nList' returned from a LINQ query. The data is correct but I have to check if the data in the 2nd field ('nType') occurs more than once, and if it does, remove it from the list if the 3rd field ('nAmount') is null.
To illustrate, in the example below, I would want to remove the record with ID 2.
Can this be done using LINQ?
EDIT: There can only be 2 scenarios:
one occurrence of nType, with nAmount populated
two occurences of nType, with one nAmount populated, the other nAmount null
ID nType nAmount
1 A 12.00
2 A
3 B 13.00
4 C 14.00
var result = nList.Where(x => x.nAmount != null).DistinctBy(x => x.nType);
You would need to install MoreLinq from Nuget to get the DistinctBy().
This can be done with a GroupBy overload which lets you define the grouped object
var result = nList.GroupBy(
x => x.nType,
(key,g) => new {
ID = g.First(x => x.nAmount != null).ID,
nType = key,
nAmount = g.First(x => x.nAmount != null).nAmount }
);
Live example: http://rextester.com/PFX41986
This has a few caveats
If your resultset has a single nType which has a null nAmount it will not appear in the results
If you get more than 1 distinct nType with a non-null nAmount this will take the first one.
I have an entity in my model that has an integer property:
public class Foo
{
public int SortOrder { get; set; }
// ...other props
}
Now, for some subset of all the Foos in the database, I want to select the highest SortOrder and add one - i.e. get the sort order for a new object added last in the collection - but if there are no Foos in that subset, I want to end up with 0 - i.e. the sort order of a new object added to an empty collection.
Reading this reference page, I got the impression that .Max() returns null if the collection over which it aggregates is empty, so I tried the following:
var sortOrder = context.Foos
.Where(/* predicate for subset */)
.Max(foo => foo.SortOrder) + 1
?? 0;
but that doesn't compile, since the return type of .Max is inferred to be int which can't be null coalesced.
However, if I just don't use the null coalescing, and assume that .Max() really returns default(T) (i.e. 0 in this case), then I'll end up with 1 instead of 0 for the empty case. Since this is a call to the database, I'd rather make do with one query.
It works just as I want it to if I make the property on Foo to be of type int?, but I don't want to do that since we don't allow NULL values in the database and I see no reason to allow them on the entity then.
I got the impression that .Max() returns null if the collection over
which it aggregates is empty
You get an InvalidOperationException which is documented here
"InvalidOperationException... source does not contain any elements."
You can use DefaultIfEmpty(0):
int maxSortOrder = context.Foos
.Where(/* predicate for subset */)
.Select(foo => foo.SortOrder + 1)
.DefaultIfEmpty(0)
.Max();
I have the following code:
IEnumerable<DestinationResult> destinations =
_repository.GetDestinationData();
IEnumerable<Destination> finalDestinations =
destinations.Select(GetAdditionalDestinationInfo);
private Destination GetAdditionalDestinationInfo(DestinationResult d){ /* CODE */}
How can I still use the method group call (Select(GetAdditionalDestinationInfo)) and filter out the null values that might be returned from GetAdditionalDestinationInfo (without having to call the method again to check for null in a where clause).
Something like:
IEnumerable<Destination> finalDestinations =
destinations.Select(GetAdditionalDestinationInfo != null)
Select maps input records to output records, one by one - there's no opportunity for filtering. Instead, you want to add another Where:
IEnumerable<Destination> finalDestinations =
destinations
.Select(GetAdditionalDestinationInfo)
.Where(i => i != null);
List<LICENSE> licenseList = context.LICENSE.Where(l => ( string.IsNullOrEmpty(licenseID) || l.LICENSE_ID.Contains(licenseID) ) && ( string.IsNullOrEmpty(hardwareID) || l.HARDWARE_ID.Contains(hardwareID) ) ).Take(10).ToList();
This is my current solution for handling more than one searchbox. Its a search function that combines 2 or more textfields in to a search. So my questions are: Is this an ok way to filter out the passed searchstrings. And how do i use it when the queries are decimals instead of strings? Thanks
Your example is perfectly fine.
With regards to it being decimals:
If it is a nullable type, then you first have to check if it has a value, and if it has that it is not the default value for a decimal which is 0.
If it is not a nullable type, then all you have to do is check that it is/is not == to 0 which is the default type. I always just check to make sure it's greater than zero, based on the assumption that a license won't be negative.
I am going to assume that it's not a nullable type as it seems to be an inline declared var, so here is a formatted example for decimal:
List<LICENSE> licenseList =
context.LICENSE.Where(l => licenseID == 0 || l.LICENSE_ID.Contains(licenseID))
.Where(l => hardwareID == 0 || l.HARDWARE_ID.Contains(hardwareID))
.Take(10)
.ToList();
Interesting thing to note, if you don't know the default type of a field, you can always do
licenseID == default(decimal)
You may try using a foreach loop on the search boxes, modifying linq, for any of those.
object[] a = {"seach", 5}; // "Data"
string[] Search = { "asdf", "asdf" }; //Search boxes
var s = a.Where(l => ((string)l).Contains(Search[0])); //first search
for (int i = 1; i < Search.Length; i++) //consecutive searches
s = s.Where(l => ((string)l).Contains(Search[i]));
Yes it looks ok. You could also use a loop somehow like this:
var query = context.LICENSE;
foreach(var item in stringVariables) {
query = query.Where(x => string.IsNullOrEmpty(item) || l.LICENSE_ID.Contains(item));
}
and stringVariables can be predefined or some algorithm to decide whether it's a search field or not.
Concerning the numbers (and assuming your column has type int, if it is a string you don't have to change anything), you probably have a nullable number, depending on your search form. So, you also have to check whether it's null or not and whether it's the right number. You may want to cast it to a string to also have the Contains function. But that all depends on your application.