LINQ query with Left Join, Group by without null List - linq

I am working on LINQ query with Left-Join and groupBy, so I have list of questions which may or may not have answer collections. I want all the question group by question and their answer list, if it is null then don't want to add.
My current solution works fine but it still add a list with null where no answer is there hence giving me wrong result on Answer count()
var dhd = (from question in Context.Questions
join answer in Context.Answers on question.Id equals answer.QuestionId into ps
from answerDetail in ps.DefaultIfEmpty()
group answerDetail by question into grouped
select new
{
Question = grouped.Key,
Answer = grouped.ToList(),
//Answer = grouped.ToList() == null ? "(No Answer)" : grouped.Select(x => x.Value).FirstOrDefault(),
TotalAnswerCount = grouped.Count()
}).ToList();
I have tried following script in above code and it throw null exception
Answer = grouped.ToList() == null ? "(No Answer)" : grouped.Select(x => x.Value).FirstOrDefault(),

When you call ps.DefaultIfEmpty() it's making a list with null for non-matching element. If you want to get just null instead of a list with a null element, then try this code:
Answer = grouped.FirstOrDefault() == null ? null : grouped.ToList(),
If there's no match, then Answer is null, otherwise you get a list.

I think issue occur because of type so try this one:
Answer = grouped.ToList() == null ? null : grouped.Select(x => x.Value).FirstOrDefault(),

Related

Why is this LINQ to EF query not working?

I have a problem with the following method:
public IQueryable<Customer> ListCustomers(int? parentId)
{
Debug.Assert(parentId == null);
//var list = _customerRepository.List().Where(c => c.ParentId == null);
var list = _customerRepository.List().Where(c => c.ParentId == parentId);
return list;
}
I have one Customer in my DB with a ParentId of null. When I call the method with ListCustomers(null), list is empty for the return statement. If I swap the commented out line in and query with a hard-coded null, then list contains my one customer.
What could cause this difference between these two queries? Why is the one with c.ParentId == parentId not returning anything?
Becouse the Nullable type the linq provider will not generate the proper IS NULL check. See this answer for further information: https://stackoverflow.com/a/785501/1195510
EF translates your query with int? to something like this:
DECLARE #parentId Int = null
SELECT ... WHERE ParentId = #parentId
When this is executed on the database, it doesn't do what you expect because in SQL [column] = NULL is always false.
I agree EF could handle this better, but as a workaround, you can write something like this:
.Where( c => !parentId.HasValue
? !c.ParentId.HasValue
: c.ParentId.Value == parentId.Value
)
EF will then generate a ( somewhat verbose ) SQL statement with the correct IS NULL predicates.
with nullable types you have to use it like this:
.Where(c=> object.Equals(c.ParentId, parentId))

LINQ NullReferenceException on DefaultIfEmpty

I'm looking for a solution to the problem of having the DefaultIfEmpty() extension method not picking up null values when used in a LINQ outer join.
Code as follows:
var SummaryLossesWithNets = (from g in SummaryLosses
join n in nets
on g.Year equals n.Year into grouping
from x in grouping.DefaultIfEmpty()
select new
{
Year = g.Year,
OEPGR = g.OccuranceLoss,
AEPGR = g.AggregateLoss,
OEPNET = ((x.OEPRecovery == null) ? 0 : x.OEPRecovery),
AEPNET = ((x.AEPRecovery == null) ? 0 : x.AEPRecovery),
});
In the List SummaryLosses there are many years worth of data I wish to join to the table 'nets' which contains a sub-portion of the years. The exception is thrown on x being a null value, I am assuming because the years in SummaryLosses not matched by years in nets creates null values in the grouping list.
How should one go about checking for the null value here? As you can see I've attempted to check for null on the properties of x, but since x is null this doesn't work.
Kind regards
Richard
Simply check whether x is null instead:
OEPNET = x == null ? 0 : x.OEPRecovery,
AEPNET = x == null ? 0 : x.AEPRecovery
Or if x.OEPRecovery and x.AEPRecovery are nullable properties too, use:
OEPNET = x == null ? 0 : (x.OEPRecovery ?? 0),
AEPNET = x == null ? 0 : (x.AEPRecovery ?? 0)
If you have many join statements
check check all joined tables and ensure that the foreign key you are using
(in comparing or lets say Interested in) is not null

Filter a generic list based on a reflected value of its entries with linq

I have a generic list of objects from which I want to whittle down based on a reflected value within it
List<MyCaseObj> CasesInGroup = ....;
PropertyInfo piItem = typeof(MyCaseObj).GetProperty(SomePropertyName).PropertyType.GetProperty(SomeValueMemberName);
var CasesToProcess = (from csh in CasesInGroup
where ((Guid)piItem.GetValue(piField.GetValue(csh, null), null))
.In(fld.Items.Select(i => i.ItemID))
select csh);
however it transpires that the particular value may sometimes be null, and the In extension is not to fond of that throwing a 'Non-static method requires a target.' exception
adding a && (Guid)piItem.GetValue(piField.GetValue(csh, null), null) != null doesn't work, and does the reflection twice anyway which doesnt seem right in the first place even if it did..
could someone explain how to get around this, or maybe just a nicer way to do this in the first place.
any help, pointers or such would be gratefully recieved
thanks
You could replace
(Guid)piItem.GetValue(piField.GetValue(csh, null), null))
with
(csh != null ? (Guid)piItem.GetValue(piField.GetValue(csh, null), null)) : Guid.Empty)
which should work unless Items sometimes contains Guid.Empty.
P.S. If you are up for learning something very, very cool, convert this expression to a lambda:
var myCaseType = typeof(MyCaseObj);
var param = Expression.Parameter(myCaseType);
var cond = Expression.Condition(
Expression.NotEqual(param, Expression.Constant(null, myCaseType))
, Expression.Property(param, "SomePropertyName")
, Expression.Constant(Guid.Empty)
);
var lambda = (Func<MyCaseObj,Guid>)Expression.Lambda(cond, param).Compile();
You can now re-write your select like this:
var CasesToProcess = (from csh in CasesInGroup
where lambda(csh)In(fld.Items.Select(i => i.ItemID))
select csh);

Linq check to see is there any NULLs in a set of DataRows?

I have a set DataRows and I want to check if any of the fields in any of those rows has a NULL value in it. I came up with this below, but I'm not sure because I'm nesting an ALL.
result.AsEnumerable().AsQueryable().All(o => o.ItemArray.All(i=>i == DBNull.Value))
Hard to tell because I can't put a "watch" in lambdas.
Actually you need to use Any (in your code you will return true if All values are null) and AsQueryable() is useless in this case.
bool nullFound = result.AsEnumerable()
.Any(o => o.ItemArray.Any(i=>i == DBNull.Value || i == null));
Then, If you need a list of all rows with some value null, just do the following:
var rowsWithNulls = result.AsEnumerable()
.Where(o => o.ItemArray.Any(i=>i == DBNull.Value || i == null))
.ToList();
P.S.
I also added a null check to be more safe, but if you are sure to have only DBNull.Value, you can remove it.
Not sure if this is the correct answer. I'm also rather new to Linq, but i believe you can do something like this;
result.AsEnumerable().AsQueryable().SingleOrDefault(o => o.ItemArray.All(i=>i == DBNull.Value))
This will return an list of items or null if there aren't any. Not sure if you can also nest it, but don't see why it wouldn't be possible

Can't enumerate LinQ results with left join

var itemSet = from item in da.GetList<Models.account>()
join file in objFileStorageList
on item.account_id equals file.parent_id into objFile
from fileItem in objFile.DefaultIfEmpty()
where item.company != null && item.company.company_id == 123
orderby item.updatedDate descending
select
new
{
Id = item.account_id,
RefNo = item.refNo,
StartDate = item.StartDate ,
EndDate = item.EndDate ,
Comment = item.comment,
FileStorageID = fileItem != null ? fileItem.fileStorage_id : -1,
Identification = fileItem != null ? fileItem.identifier : null,
fileName = fileItem != null ? fileItem.file_nm : null
};
It raises error message when I try to enumerate through collection result from Linq query above.
LINQ to Entities does not recognize
the method
'System.Collections.Generic.IEnumerable1[SCEFramework.Models.fileStorage]
DefaultIfEmpty[fileStorage](System.Collections.Generic.IEnumerable1[SCEFramework.Models.fileStorage])'
method, and this method cannot be
translated into a store expression
foreach (var item in itemSet)
{
string itemRef= item.RefNo;
}
Please suggest me any solutions.
Thanks in advance.
I think the problem with this is the following 'from' clause:
from fileItem in objFile.DefaultIfEmpty()
Note that your LINQ query may only be executed at the time the result collection is executed. So while you think your exception is in the foreach, it's actually within your expression. This breaks because the possible null value of objFile.DefaultIfEmpty() cannot cast into an IEnumerable.
Try removing the DefaultIfEmpty call and see what happens.

Resources