foreach (var incident in new DataAccess.IncidentRepository().GetItems().Where(
i => (startDate == null || i.IncidentDate >= startDate)
&& (endDate == null || i.IncidentDate <= endDate)
&& (shiftId == null || i.ShiftId == shiftId)
&& (processAreaId == null || i.ProcessAreaId == processAreaId)
&& (plantId == null || i.PlantId == plantId)))
is there a way I can i.PlantId == plantId not to get added if plantId is null?
Thanks
var incident in new DataAccess.IncidentRepository().GetItems().Where(
i => i.IncidentDate >= startDate
&& i.IncidentDate <= endDate
&& i.ShiftId == shiftId
&& i.ProcessAreaId == processAreaId
&& (plantId == null || i.PlantId == plantId)))
Alternatively, you could:
var incidents = new DataAccess.IncidentRepository().GetItems().Where(
i => i.IncidentDate >= startDate
&& i.IncidentDate <= endDate
&& i.ShiftId == shiftId
&& i.ProcessAreaId == processAreaId));
if (plantId != null)
incidents = incidents.Where(i => i.PlantId == plantId);
foreach (var incident in incidents) {
// ...
}
var incident in new DataAccess.IncidentRepository().GetItems().Where(
i => i.IncidentDate >= startDate
&& i.IncidentDate <= endDate
&& i.ShiftId == shiftId
&& i.ProcessAreaId == processAreaId
&& object.Equals(i.PlantId, plantId)))
Related
I have just done the upgrade from EF Core 2.2 to EF Core 3.1. I have some queries like this:
...
userIdList.All(u => _context.ConversationUsers.Count(x => x.ContextOwnerCode == t.ContextOwnerCode && x.CompanyCode == u.CompanyCode && x.ConversationId == t.Id && x.UserId == u.ElementId &&
(x.GroupId == null || x.GroupId == 0) && (x.Deleted == null || !(bool)x.Deleted)) > 0) &&
_context.ConversationUsers.Count(x => x.ConversationId == t.Id && (x.GroupId == null || x.GroupId == 0) &&
(x.Deleted == null || !(bool)x.Deleted) && userIdList.Count(u => u.CompanyCode == x.CompanyCode && u.ElementId == x.UserId) == 0) == 0)
...
here the userIdList is a list that needs to be compared with data in the database. With EF Core 3 this function is no more translated.
One solution could be to use AsEnumerable() or ToList() but in my case is not a good solution since I have a huge amount of data and it is not possible to get all the data on the client side.
EDIT
This is the full query:
var result = _context.Conversations.Where(t => t.ContextOwnerCode == contextOwnerCode &&
((docYear == 0 && docCode == 0) ||
(docYear != 0 && docCode != 0 && t.DocumentYear != null && t.DocumentCode != null && t.DocumentYear == docYear && t.DocumentCode == docCode)) &&
(
(senderGroup != null && senderGroup.CompanyCode > 0 && senderGroup.ElementId > 0 && recipientGroup != null && recipientGroup.CompanyCode > 0 && recipientGroup.ElementId > 0 &&
(userIdList == null || userListCount == 0) &&
t.CreatedChatGroupId != null && t.ChatGroupId != null && t.CreatedChatGroupId > 0 && t.ChatGroupId > 0 &&
((senderGroup.CompanyCode == t.CreatedCompanyCode && senderGroup.ElementId == t.CreatedChatGroupId &&
recipientGroup.CompanyCode == t.ChatGroupCompanyCode && recipientGroup.ElementId == t.ChatGroupId) ||
(senderGroup.CompanyCode == t.ChatGroupCompanyCode && senderGroup.ElementId == t.ChatGroupId &&
recipientGroup.CompanyCode == t.CreatedCompanyCode && recipientGroup.ElementId == t.CreatedChatGroupId))) ||
(((senderGroup != null && senderGroup.CompanyCode > 0 && senderGroup.ElementId > 0 &&
(recipientGroup == null || (recipientGroup.CompanyCode == 0 && recipientGroup.ElementId == 0))) ||
((senderGroup == null || (senderGroup.CompanyCode == 0 && senderGroup.ElementId == 0)) &&
recipientGroup != null && recipientGroup.CompanyCode > 0 && recipientGroup.ElementId > 0)) &&
userIdList != null && userListCount > 0 &&
((senderGroup != null && t.CreatedChatGroupId != null && t.ChatGroupCompanyCode == null && t.ChatGroupId == null &&
senderGroup.CompanyCode == t.CreatedCompanyCode && senderGroup.ElementId == t.CreatedChatGroupId) ||
(recipientGroup != null && t.CreatedChatGroupId == null && t.ChatGroupCompanyCode != null && t.ChatGroupId != null &&
recipientGroup.CompanyCode == t.ChatGroupCompanyCode && recipientGroup.ElementId == t.ChatGroupId)) &&
userIdList.All(u =>
_context.ConversationUsers.Count(x => x.ContextOwnerCode == t.ContextOwnerCode && x.CompanyCode == u.CompanyCode && x.ConversationId == t.Id && x.UserId == u.ElementId &&
(x.GroupId == null || x.GroupId == 0) && (x.Deleted == null || !(bool)x.Deleted)) > 0) &&
_context.ConversationUsers.Count(x => x.ConversationId == t.Id && (x.GroupId == null || x.GroupId == 0) &&
(x.Deleted == null || !(bool)x.Deleted) && userIdList.Count(u => u.CompanyCode == x.CompanyCode && u.ElementId == x.UserId) == 0) == 0) ||
((senderGroup == null || (senderGroup.CompanyCode == 0 && senderGroup.ElementId == 0)) &&
recipientGroup != null && recipientGroup.CompanyCode > 0 && recipientGroup.ElementId > 0 &&
(userIdList == null || userListCount == 0) &&
t.CreatedChatGroupId == null && t.ChatGroupCompanyCode != null && t.ChatGroupId != null &&
recipientGroup.CompanyCode == t.ChatGroupCompanyCode && recipientGroup.ElementId == t.ChatGroupId &&
_context.ConversationUsers.Count(x => x.ConversationId == t.Id && (x.GroupId == null || x.GroupId == 0) && (x.Deleted == null || !(bool)x.Deleted)) == 0) ||
((senderGroup == null || (senderGroup.CompanyCode == 0 && senderGroup.ElementId == 0)) &&
(recipientGroup == null || (recipientGroup.CompanyCode == 0 && recipientGroup.ElementId == 0)) &&
userIdList != null && userListCount > 1 &&
userIdList.All(u =>
_context.ConversationUsers.Count(x => x.ContextOwnerCode == t.ContextOwnerCode && x.CompanyCode == u.CompanyCode && x.ConversationId == t.Id && x.UserId == u.ElementId &&
(x.GroupId == null || x.GroupId == 0) && (x.Deleted == null || !(bool)x.Deleted)) > 0) &&
_context.ConversationUsers.Count(x => x.ConversationId == t.Id && (x.GroupId == null || x.GroupId == 0) &&
(x.Deleted == null || !(bool)x.Deleted) && userIdList.Count(u => u.CompanyCode == x.CompanyCode && u.ElementId == x.UserId) == 0) == 0)
)
).FirstOrDefault();
My recommendation here is to convert the above query to SQL Store Procedure.
There is a good tool called LinqPad you can use to make the conversion easier.
P.S. in the above code you can try to use !Any(...) method instead of Count(...) == 0.
I want to make a query using entity framework with some restrictions. The issue is that sometimes there are no restrictions, so I don´t know if what I doing is the best practice.
My EF code is as:
Get(x => x.CreationDate >= filterInit
&& x.CreationDate <= filterEnd
&& x.Cond1 > ax
&& x.Cond2 > y).ToListAsync();
If ax is, for example, null, I do this:
if(ax == null){
Get(x => x.CreationDate >= filterInit
&& x.CreationDate <= filterEnd
&& x.Cond2 > y).ToListAsync();
}else if(y == null)
{
Get(x => x.CreationDate >= filterInit
&& x.CreationDate <= filterEnd
&& x.Cond1 > ax ).ToListAsync();
}else{
Get(x => x.CreationDate >= filterInit
&& x.CreationDate <= filterEnd
&& x.Cond1 > ax
&& x.Cond2 > y).ToListAsync();
}
I´m sure that there is a pretty way to do this, but I dont know how.
Could you please help me with this?
The normal idiom for this is
IQueryable<SomeEntity> q = ...;
if (ax != null)
{
q = q.Where(x => x.Cond1 == ax);
}
if (y != null)
{
q = q.Where(x => x.Cond2 == y);
}
Check for null variable values within the query and use them if not null:
Get(x => x.CreationDate >= filterInit
&& x.CreationDate <= filterEnd
&& (ax == null || x.Cond1 > ax)
&& (y == null || x.Cond2 > y))
.ToListAsync();
I want to find the data in database when any one of the conditions meet.
Pasted my code so that it will be more clear
[HttpGet]
[Route("")]
public IEnumerable<User> GetUsers(string FirstName = null, string LastName = null, int Year = 0, int Month = 0)
{
var users = _context.Users.AsQueryable();
if (FirstName != null || LastName != null || Year != 0 || Month != 0)
{
users = _context.Users.Where(u => (u.CreatedAt.Year == Year) && (u.CreatedAt.Month == Month));
}
else
{
users = _context.Users;
}
return users.ToList();
}
This code is doing a simple search in database
where year == createdAt.year &&
month == createdAt.month &&
LastName == abc &&
FirstName == abc
However, if one of the condition is 0/null, then the database will return nothing since there is no month/year == 0 or firstname/lastname == null; What I want is, if year/month/lastname/firstname is 0/null, then just ignore it and check other condition.
Any idea?
// first style
users = _context.Users.Where(u =>
(Year != 0 ? u.CreatedAt.Year == Year : true) &&
(Month != 0 ? u.CreatedAt.Month == Month : true) &&
(FirstName != null ? u.FirstName == FirstName : true) &&
(LastName != null ? u.LastName == LastName : true));
// second style
users = _context.Users.Where(u =>
(Year == 0 || u.CreatedAt.Year == Year) &&
(Month == 0 || u.CreatedAt.Month == Month) &&
(FirstName == null || u.FirstName == FirstName) &&
(LastName == null || u.LastName == LastName));
I think you should check each condition separately like this.
For example when Year != 0 and every other para is not set, your original code will return nothing.
You can add your logic to the LINQ query to check conditions.
users = _context.Users.Where(x => x.Id !=0
&& x.FirstName != null
&& x.FirstName != null
&& x.Year != 0
&& x.Month != 0)
.ToList();
Try this users = _context.Users.Where(x =>
&& (x.FirstName != null || x.FirstName == FirstName)
&& (x.Year == 0 || x.Year == Year)
&& (x.Month == 0 || x.Month == Month)
.ToList();
Here is an example of the SQL I am trying to convert to Linq
SELECT
* FROM assetassignment
WHERE asgn_type = 'trc' AND asgn_id = '54490' AND lgh_number <> 3015097 AND mov_number <>2030782
and asgn_enddate in (select max(asgn_enddate) FROM assetassignment
WHERE asgn_type = 'trc' AND asgn_id = '54490' AND lgh_number <> 3015097 AND mov_number <> 2030782 and asgn_enddate <= '03/19/2017')
I need to convert this to Linq. I am using a repository as follows:
public async task<AssetAssignment> FindPreviousTrip(string tractorNumber, DateTime endDate, int legNumber,string moveNumber)
{
using (var ctx = new AssetAssignmentContext(_nameOrConnectionString))
{
var previousTrip = from a in ctx.Set<AssetAssignment>()
where a.AssignmentType == "TRC" &&
a.AssignmentId == tractorNumber &&
a.LegId == legNumber &&
a.MoveNumber == moveNumber &&
a.EndDate).in()
}
}
As you can see I am making a stab at it, but keep failing on the subquery for the EndDate in statement.
I'll keep plugging at it, but any help is appreciated.
var previousTrip = from a in ctx.Set<AssetAssignment>()
where a.AssignmentType == "TRC" &&
a.AssignmentId == tractorNumber &&
a.LegId != legNumber &&
a.MoveNumber != moveNumber &&
a.EndDate == (from b in ctx.Set<AssetAssignment>()
where b.AssignmentType == "TRC" && b.AssignmentId == tractorNumber && b.LegId != legNumber && b.MoveNumber != moveNumber && b.EndDate <= new DateTime(2017, 19, 3)
select b.EndDate).Max()
select a;
You may want to create a variable for the common query
var baseTrip = from a in ctx.Set<AssetAssignment>()
where a.AssignmentType == "TRC" &&
a.AssignmentId == tractorNumber &&
a.LegId != legNumber &&
a.MoveNumber != moveNumber
select a;
var previousTrip = from a in baseTrip
where a.EndDate == (from b in baseTrip where b.EndDate <= new DateTime(2017, 19, 3) select b.EndDate).Max()
select a;
In my ASP.net MVC project, I've a search form with a total of 7 search variables. None of them are mandatory, however, at least one should be selected to perform search operation, as shown in the image.
What is the best method to perform search using lambda expression in this scenario since any combination of search parameters can be selected by the user? For now, I'm using a long list of 'if-else if' structures and writing individual lambda expressions for each. Is there a better/ more efficient way?
Update 1:
This is just half of the conditions, and now I've been told that even the 'Date To' for each of the three date criteria are optional, which will increase the list of checks even more. Is this the standard way of doing it?
IEnumerable<MyRecord> Request = null;
if (!status.Equals(""))
{
if (deliveryDateFrom == null && caseDateFrom == null && pickupDateFrom == null)
{
//only request status
Request = GetRecord("EquipRequest")
.Where(r => r.Status == status);
}
else if (deliveryDateFrom != null && caseDateFrom == null && pickupDateFrom == null)
{
// request status and delivery date
Request = GetRecord("EquipRequest")
.Where(r => r.Status == status && (r.DeliveryDate >= deliveryDateFrom && r.DeliveryDate <= deliveryDateTo));
}
else if (deliveryDateFrom == null && caseDateFrom != null && pickupDateFrom == null)
{
// request status and case date
Request = GetRecord("EquipRequest")
.Where(r => r.Status == status && (r.CaseDate >= caseDateFrom && r.CaseDate <= caseDateTo));
}
else if (deliveryDateFrom == null && caseDateFrom == null && pickupDateFrom != null)
{
// request status and pickup date
Request = GetRecord("EquipRequest")
.Where(r => r.Status == status && (r.PickupDate >= pickupDateFrom && r.PickupDate <= pickupDateTo));
}
else if (deliveryDateFrom != null && caseDateFrom != null && pickupDateFrom == null)
{
// request status, delivery date and case date
Request = GetRecord("EquipRequest")
.Where(r => r.Status == status && (r.DeliveryDate >= deliveryDateFrom && r.DeliveryDate <= deliveryDateTo)
&& (r.CaseDate >= caseDateFrom && r.CaseDate <= caseDateTo));
}
else if (deliveryDateFrom != null && caseDateFrom == null && pickupDateFrom != null)
{
// request status, delivery date and pickup date
Request = GetRecord("EquipRequest")
.Where(r => r.Status == status && (r.DeliveryDate >= deliveryDateFrom && r.DeliveryDate <= deliveryDateTo)
&& (r.PickupDate >= pickupDateFrom && r.PickupDate <= pickupDateTo));
}
else if (deliveryDateFrom == null && caseDateFrom != null && pickupDateFrom != null)
{
// request status, case date and pickup date
Request = GetRecord("EquipRequest")
.Where(r => r.Status == status && (r.CaseDate >= caseDateFrom && r.CaseDate <= caseDateTo)
&& (r.PickupDate >= pickupDateFrom && r.PickupDate <= pickupDateTo));
}
else if (deliveryDateFrom != null && caseDateFrom != null && pickupDateFrom != null)
{
// request status, delivery date, case date and pickup date
Request = GetRecord("EquipRequest")
.Where(r => r.Status == status && (r.DeliveryDate >= deliveryDateFrom && r.DeliveryDate <= deliveryDateTo)
&& (r.CaseDate >= caseDateFrom && r.CaseDate <= caseDateTo)
&& (r.PickupDate >= pickupDateFrom && r.PickupDate <= pickupDateTo));
}
}
What you could do is use a function like the following:
public static IEnumerable<TSource> WhereIf<TSource>(this IEnumerable<TSource> source, bool condition, Func<TSource, bool> predicate)
{
return condition ? source.Where(predicate) : source;
}
What it will do is if the bool is true, it will narrow it down by your lambda expression, if it is false, it will just continue.
And used it like so:
var whatever = GetRecord("EquipRequest")
.Where(r.Status == status)
.WhereIf(deliveryDateFrom != null, r => r.DeliveryDate >= deliveryDateFrom)
.WhereIf(deliveryDateTo != null, r => r.DeliveryDate <= deliveryDateTo)
.WhereIf(caseDateFrom != null, r => r.CaseDate >= caseDateFrom)
.WhereIf(caseDateTo != null, r => r.CaseDate <= caseDateTo)
.WhereIf(pickupDateFrom != null, r => r.PickupDate >= pickupDateFrom)
.WhereIf(pickupDateTo != null, r => r.PickupDate <= pickupDateTo)
So on and so forth
First I recommend you get LinqPad, learn it, if you want to experiment with things like this.
Then write something like this LinqPad script and run it to get your Linq statement correct:
public class SearchViewModel {
public DateTime DeliveryDateFrom {get; set;}
public DateTime DeliveryDateTo {get; set;}
public DateTime CaseDateFrom {get; set;}
public DateTime CaseDateTo {get; set;}
public DateTime PickupDateFrom {get; set;}
public DateTime PickupDateTo {get; set;}
};
public class Data {
public DateTime DeliveryDate {get; set;}
public DateTime CaseDate {get; set;}
public DateTime PickupDate {get; set;}
};
void Main()
{
var model = new SearchViewModel(); // insert your model stuff here
// you can use LinqPad to hook up directly to your project DBContext dll here
var dataBase = new List<Data>() {
new Data() { DeliveryDate = DateTime.Now, CaseDate = DateTime.Now, PickupDate = DateTime.Now }
};
// experiment with Linq statement here
var result = dataBase.Where(x =>
(model.DeliveryDateFrom >= x.DeliveryDate && model.DeliveryDateTo <= x.DeliveryDate) &&
(model.CaseDateFrom >= x.CaseDate && model.CaseDateTo <= x.CaseDate) &&
(model.PickupDateFrom >= x.PickupDate && model.PickupDateTo <= x.PickupDate)
);
result.Dump();
}
You can chain where clause.
IEnumerable<MyRecord> query = GetRecord("EquipRequest");
if (!status.Equals(""))
{
if (deliveryDateFrom.HasValue)
query = query.Where(x => x.DeliveryDate >= deliveryDateFrom);
if (deliveryDateTo.HasValue)
query = query.Where(x => x.DeliveryDate <= deliveryDateTo);
}
IEnumerable<MyRecord> result = query.ToList();