C#: Nested If else condition in LINQ - c#

I am using below LINQ Query, now i want to if else condition inside LINQ Query like below- how i can achieve the same ?
if(stemming)
highlightedText = c.Value.p_content != null && c.Value.p_content[0] != null ? c.Value.p_content[0] : string.Empty
if(phoentic)
highlightedText = c.Value.s_content != null && c.Value.s_content[0] != null ? c.Value.s_content[0] : string.Empty
if(content)
highlightedText = c.Value.content != null && c.Value.content[0] != null ? c.Value.content[0] : string.Empty
Complete code -
var highlightedDataLst = objJson.highlighting.Select(c =>
new finalOutput
{
highlightedKey = c.Key,
highlightedText = c.Value.content != null && c.Value.content[0] != null ? c.Value.content[0] : string.Empty
}).ToList<finalOutput>();

Hmm taking a stab at it, it might look something like this:
var highlightedDataLst = objJson.highlighting.Select(c =>
new finalOutput
{
highlightedKey = c.Key,
highlightedText = (stemming ? c.Value.p_content?[0] :
(phoentic ? c.Value.s_content?[0] :
(content ? c.Value.content?[0] : null))) ?? ""
}).ToList<finalOutput>();
You can simplify your conditions using the null conditional operator (?[]) and null coalescing operators (??).

Related

LINQ Conditional OrderBy

I'm trying to do a conditional OrderBy but it's having no effect. The List outputs the same with default ordering.
I've tried both approaches suggested in this question Conditional "orderby" sort order in LINQ
var query = _context.Groups
.Where(gr => gr.Status != ((sbyte)ActiveStatus.DELETED)
&& gr.OrganisationId == user.OrganisationId
&& (search != null && gr.Name != null ? (gr.Name.Contains(search)) : true == true)
)
.Select(GroupReportModel.Projection);
if(!pager.Sort.HasValue || pager.Sort.Value == ((int)Sort.MODIFIED))
query.OrderByDescending(gr => gr.Created.Date);
if(pager.Sort.Value == ((int)Sort.NAME))
query.OrderByDescending(gr => gr.Name);
pager.TotalRecords = query.Count();
var list = query.Skip(pager.PageCount != null ? pager.PageCount.Value * (pager.Page.Value) : 0)
.Take(pager.PageCount != null ? pager.PageCount.Value : 0)
.ToList();
LINQ methods do not mutate the query object, they return a new one, you need to reassign it:
if(!pager.Sort.HasValue || pager.Sort.Value == ((int)Sort.MODIFIED))
query = query.OrderByDescending(gr => gr.Created.Date);
if(pager.Sort.Value == ((int)Sort.NAME))
query = query.OrderByDescending(gr => gr.Name);
....

Concatenate two strings and get null if both are null

I am looking for a solution to concatenate two string values and get null as a result if both are null.
None of string1 + string2, string.Concat(string1, string2), string.Join(string1, string2) work. Research shows that is due to the fact, that these methods internally treat null as empty string.
How to solve this?
Since your actual formula is
(a + b) ?? (c + d) // assumes that null + null == null in (a + b)
I suggest rewriting it into
a == null && b == null ? c + d : a + b
which provides the expected result:
if both a and b are null we have c + d
a + b otherwise
If you want to have null (not empty string) when all a, b, c, d are null:
a == null && b == null ?
c == null && d == null
? null
: c + d
: a + b;
Something like this?
public class StringTest
{
public string CustomConcat(string one, string two) =>
one == null && two == null
? null
: string.Concat(one, two);
[Test]
public void ConcatTest()
{
Assert.IsNull(CustomConcat(null, null));
Assert.AreEqual("one", CustomConcat("one", null));
Assert.AreEqual("two", CustomConcat(null, "two"));
Assert.AreEqual("onetwo", CustomConcat("one", "two"));
// finally, a test for (a + b) ?? (c + d)
Assert.AreEqual("threefour", CustomConcat(null, null) ?? CustomConcat("three", "four"));
}
}
Yes, different method calls treat different preconditions, but you can always create your own function to handle "custom" preconditions.
As the most simple option you can try something like this:
String concatenateStrings(string s1, string s1) {
return (s1 == null && s2 == null)? null : String.concat(s1,s2);
}
You could do this:
var textResult = string.Empty;
if (string.IsNullOrWhiteSpace(text1) &&
string.IsNullOrWhiteSpace(text2))
{
textResult = null;
}
else
if (!string.IsNullOrWhiteSpace(text1) &&
string.IsNullOrWhiteSpace(text2))
{
textResult = text1;
}
else
if (string.IsNullOrWhiteSpace(text1) &&
!string.IsNullOrWhiteSpace(text2))
{
textResult = text2;
}
textResult = $"{text1} {text2}";
or in a better way:
textResult = (!string.IsNullOrWhiteSpace(text1) &&
string.IsNullOrWhiteSpace(text2)) ?
text1 :
(string.IsNullOrWhiteSpace(text1) &&
!string.IsNullOrWhiteSpace(text2)) ?
text2 :
(string.IsNullOrWhiteSpace(text1) &&
!string.IsNullOrWhiteSpace(text2)) ?
text2 :
$"{text1} {text2}";

The 'await' operator can only be used within an async lambda expression. Consider marking this lambda expression with the 'async' modifier

In following LinQ query to get Phone Number I'm calling another async method GetAspNetUserPhoneNumberByAccountId, which throws this error
Error CS4034 The 'await' operator can only be used within an async lambda expression. Consider marking this lambda expression with the 'async' modifier.
Anyone have idea about it ?
var fullAppointment = await Task.Run(() => Context.AppointmentDetail
.Where(u =>
u.StartDateTime >= startdatetime
&& u.EndDateTime <= enddatetime
)
.Select(x => new Contracts.CalenderModel2()
{
StatusId = (Contracts.Enum.EnumWOStatus)x.Status,
FName = x.Appointment != null ? x.Appointment.Customer.Account.FName : "",
LName = x.Appointment != null ? x.Appointment.Customer.Account.LName : "",
**PrimaryPhone = x.Appointment != null ?
(await _userRepository.GetAspNetUserPhoneNumberByAccountId( x.Appointment.Customer.AccountId))**
: "",
Year = x.Appointment != null && x.Appointment.Vehicle != null ? x.Appointment.Vehicle.MakeYear.Year : 0,
Make = x.Appointment != null && x.Appointment.Vehicle != null ? x.Appointment.Vehicle.VehicleMaker.MakerName : "",
Model = x.Appointment != null && x.Appointment.Vehicle != null ? x.Appointment.Vehicle.VehicleModel.Model : "",
AppointmentId = x.AppointmentId,
JobEndDateTime = x.EndDateTime,
JobStartDateTime = x.StartDateTime,
ColorCategory = x.AppointmentType.ColorCategory,
SalesRepersentativeUserId =
(x.Appointment != null && x.Appointment.Customer.CustomerBillTo.Count > 0)
? x.Appointment.Customer.CustomerBillTo.FirstOrDefault().BillToId : Guid.Empty,
FullAppointmentDetail = new Contracts.FullAppointmentDetail
{
BayId = x.BayId,
BayName = x.WorkArea != null ? x.WorkArea.BayName : "",
WorkTypeId = x.WorkTypeId,
WorkTypeName = x.WorkType != null ? x.WorkType.WorkTypeName : "",
JobId = x.Appointment != null && x.Appointment.Job != null ? x.Appointment.Job.Id : Guid.Empty,
JobIdInt = x.Appointment != null && x.Appointment.Job != null ? x.Appointment.Job.JobIdInt : 0,
AssigneeUserId = x.AssigneeUserId,
WorkOrderId = x.WorkOrders.FirstOrDefault() != null ? x.WorkOrders.FirstOrDefault().Id : Guid.Empty
}
})
.ToList());
The Definition of GetAspNetUserPhoneNumberByAccountId is given below
public async Task<string> GetAspNetUserPhoneNumberByAccountId(Guid accountId)
{
var phone = await Task.Run(() => _Context.Account.Where(ac => ac.Id.Equals(accountId))
.Join(_Context.AspNetUsers, ac => ac.AspNetUserId, u => u.Id, (ac, u) => new
{
PhoneNumber = u.PhoneNumber,
}).FirstOrDefault());
return phone!=null?phone.ToString():"";
}
I agree with guys in the comments that you don't need to use async method in this query. In additional this query will not optimize. For each item in Where condition you will do it query to DB. If you have a lot of data, performance of DB will go down. I think in this case much better to do it 2 queries to DB. For getting AppointmentDetail and another query for getting all accounts. And both query call with async. And after that combine it to your Contracts.CalenderModel2 class.
It will be more readable and work faster.
And don't use Task.Run();

Using an OR Statement within a Return Where [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 8 years ago.
I have this return Statement,
return taskItems.Where(s => s.DateCreated >= fromDate.SelectedDate || s.DateCreated <= toDate.SelectedDate);
This should work, but Visual Studio is giving me this exception on the "InitializeComponent();",
Object reference not set to an instance of an object.
This is what's used to load the tasks into the Datagrid being used,
private IEnumerable<TaskEntry> LoadTasks()
{
var data = GetListItems("Tasks");
var result = XElement.Parse(data.OuterXml);
XNamespace z = "#RowsetSchema";
var taskItems = from r in result.Descendants(z + "row")
//where r.Attribute("ows_Created")
//where r.Attribute("ows_Client_x0020_Issue") == null
select new TaskEntry
{
ID = r.Attribute("ows_ID") != null ? r.Attribute("ows_ID").Value : string.Empty,
IssueID = r.Attribute("ows_Client_x0020_Issue") != null ? r.Attribute("ows_Client_x0020_Issue").Value : string.Empty,
Client = r.Attribute("ows_Client") != null ? r.Attribute("ows_Client").Value : string.Empty,
Title = r.Attribute("ows_Title") != null ? r.Attribute("ows_Title").Value : string.Empty,
TaskType = r.Attribute("ows_Task_x0020_Type") != null ? r.Attribute("ows_Task_x0020_Type").Value : string.Empty,
Priority = r.Attribute("ows_Priority") != null ? r.Attribute("ows_Priority").Value : string.Empty,
Status = r.Attribute("ows_Status") != null ? r.Attribute("ows_Status").Value : string.Empty,
AssignedTo = r.Attribute("ows_AssignedTo") != null ? r.Attribute("ows_AssignedTo").Value : string.Empty,
Owner = r.Attribute("ows_Owner") != null ? r.Attribute("ows_Owner").Value : string.Empty,
Body = r.Attribute("ows_Body") != null ? r.Attribute("ows_Body").Value : string.Empty,
DueDate = Convert.ToDateTime(r.Attribute("ows_DueDate").Value).Date,
DateCreated = Convert.ToDateTime(r.Attribute("ows_Created").Value).Date,
Area = r.Attribute("ows_Area") != null ? r.Attribute("ows_Area").Value : string.Empty,
GroupTask = r.Attribute("ows_Group_x0020_Task") != null ? r.Attribute("ows_Group_x0020_Task").Value : string.Empty,
};
return taskItems.Where(s => s != null && (s.DateCreated >= fromDate.SelectedDate || s.DateCreated <= toDate.SelectedDate));
}
You need to check that that values you are using for date filters are actually set. It would seem either fromDate or toDate are null or though without seeing some more code it is hard to say?

ASP.NET MVC5 Entity Framework 6 get bool = true and bool = false LINQ

I have a table that I am filtering on.
There is a filter for values 'include' which can be true or false.
I have a filter that has 3 options: true, false, & all.
So, when the filter is true, it should return rows where include = 'true'; when the filter is 'false', return where include = false; and when 'all' return where include = true or false.
Here is my code, that is not working, but I think it should be.
private ICollection<AggregationEntityViewModel> getEntities(AggregationPracticeDetailsViewModel apdvm)
{
bool? filterInclude = Convert.ToBoolean(apdvm.Filter_IncludeValue);
var a = (from e in _repository.GetAll<Entity>()
where e.include == filterInclude != null ? (bool)filterInclude : (true || false)
select e
return a;
}
It is currently returning 0 rows when filter is set to 'All' or 'False', and returning all rows when set to 'Yes'.
FYI, I have ommitted lots of code for clarity's sake.
Please help...thanks!
*EDIT: I've displayed all the code, so you can see why I want to keep it all in linq query. Thanks for all the offered solutions. I see that most solutions involve using Linq Extension methods. Is there anyway to do it in inline linq query? *
bool? filterInclude = Convert.ToBoolean(apdvm.Filter_IncludeValue);
var a = (from e in _repository.GetAll<Entity>()
from u in e.Users
where (e.AuditQuestionGroupId != null ? e.AuditQuestionGroupId : 0) == this.LoggedInEntity.AuditQuestionGroupId
&& e.BatchNumber != null && e.BatchNumber.StartsWith(apdvm.Filter_BatchNumber == null ? "" : apdvm.Filter_BatchNumber)
&& e.Name != null && e.Name.ToLower().StartsWith(apdvm.Filter_EntityName.ToLower())
&& e.EntityState != null && e.EntityState.ToLower().Contains(apdvm.Filter_StateValue == null ? "" : apdvm.Filter_StateValue.ToLower())
&& u.NIAMembershipId != null && u.NIAMembershipId.Contains(apdvm.Filter_MemberNo == null ? "" : apdvm.Filter_MemberNo)
from p in e.PracticeProfiles.DefaultIfEmpty()
join ea in _repository.GetAll<EntityAggregate>() on e.EntityId equals ea.EntityId into eas
from ea in eas.DefaultIfEmpty()
where ea.include == filterInclude != null ? (bool)filterInclude : (true || false)
group e by new { entity = e, profile = p, ea = ea } into newGroup
orderby newGroup.Key.entity.Name
select new AggregationEntityViewModel()
{
Id = newGroup.Key.ea == null ? 0 : newGroup.Key.ea.Id,
EntityId = newGroup.Key.entity.EntityId,
Include = newGroup.Key.ea == null ? (true || false) : (bool)newGroup.Key.ea.include,
BHAddress = newGroup.Key.profile == null || newGroup.Key.profile.soloOffice == null ? false : (bool)newGroup.Key.profile.soloOffice,
Incorporated = newGroup.Key.profile == null || newGroup.Key.profile.company == null ? false : (bool)newGroup.Key.profile.company,
MajorityOwned = newGroup.Key.profile == null || newGroup.Key.profile.capital == null ? false : (bool)newGroup.Key.profile.capital,
MajorityVoting = newGroup.Key.profile == null || newGroup.Key.profile.votingRights == null ? false : (bool)newGroup.Key.profile.votingRights,
Name = newGroup.Key.entity.Name,
Partnership = newGroup.Key.profile == null || newGroup.Key.profile.partnership == null ? false : (bool)newGroup.Key.profile.partnership,
PublicAccountant = newGroup.Key.profile == null || newGroup.Key.profile.publicAccountant == null ? false : (bool)newGroup.Key.profile.publicAccountant,
Trust = newGroup.Key.profile == null || newGroup.Key.profile.operatingTrust == null ? false : (bool)newGroup.Key.profile.operatingTrust,
TrustDeed = newGroup.Key.profile == null || newGroup.Key.profile.deed == null ? false : (bool)newGroup.Key.profile.deed
}).ToList();
return a;
Convert.ToBoolean returns bool, not bool?, so there is no way filterInclude != null is true.
You should use following pattern instead of ternary operator within where clause:
var query = _repository.GetAll<Entity>();
if (apdvm.Filter_IncludeValue == "true")
query = query.Where(x => x.include == true);
else if (apdvm.Filter_IncludeValue == "false")
query = query.Where(x => x.include == false);
return query;
I assumed apdvm.Filter_IncludeValue is a string (and that's why you tried to call Convert.ToBoolean on it).
You could use
private ICollection<AggregationEntityViewModel> getEntities(
AggregationPracticeDetailsViewModel apdvm)
{
bool? filterInclude = apdvm.Filter_IncludeValue.ConvertToNullable<bool>();
var a = (from e in _repository.GetAll<Entity>()
where !filterInclude.HasValue || ea.include == filterInclude.Value
select new AggregationEntityViewModel()
{
Include = newGroup.Key.ea == null
? (true || false)
: (bool)newGroup.Key.ea.include,
}
return a;
}
just remove your (true||false) and add filterInclude == null in the where
For Nullable Value (taken from Convert string to nullable type (int, double, etc...))
public static T? ConvertToNullable<T>(this String s) where T : struct
{
try
{
return (T?)TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(s);
}
catch (Exception)
{
return null;
}
}
There is an other solution:
var query = from e in _repository.GetAll<Entity>();
if (filterInclude.HasValue)
{
// when filterInclude is null (it means **ALL**),
// do not filter otherwise - check the flag
query = query.Where(entity => entity.Include == filterInclude.Value);
}
// or one-line:
// query = query.Where(entity => filterInclude == null
// || entity.Include == filterInclude.Value);
var a = query.Select(entity => new AggregationEntityViewModel { .... });
return a;
Other problem is that Convert.ToBoolean never returns null. You should create own method to parse apdvm.Filter_IncludeValue.
In order to convert to nullable type, you colud use the generic method:
public static Nullable<T> ToNullable<T>(this string s) where T: struct
{
Nullable<T> result = new Nullable<T>();
try
{
if (!string.IsNullOrEmpty(s) && s.Trim().Length > 0)
{
TypeConverter conv = TypeDescriptor.GetConverter(typeof(T));
result = (T)conv.ConvertFrom(s);
}
}
catch { }
return result;
}
Source.
Usage:
var filterInclude = apdvm.Filter_IncludeValue.ToNullable<bool>();
You can make it easier with fluent syntax like this:
private ICollection<AggregationEntityViewModel> getEntities(AggregationPracticeDetailsViewModel apdvm)
{
var query = _repository.GetAll<Entity>();
if(apdvm.Filter_IncludeValue != 'all')
{
var value = Convert.ToBoolean(apdvm.Filter_IncludeValue);
query = query.Where(q => q.include == value)
}
return query.Select(q => new AggregationEntityViewModel {...}).ToArray();
}
no need to evaluate string to nullable bool or smth. Same as no need to do strange boolean expressions.

Categories

Resources