I'm using this code for getting the data by month and year but it's not the right result. See the code
var result = uow.CompliedInspectionRepository.All
.Where(c => c.IsCompleted == false || c.IsCompleted == null
&& (c.DueDate.Value.Month == i && c.DueDate.Value.Year == year));
any suggestion or how to do it in EF?
you might have the brackets in the wrong place
c.IsCompleted == false || c.IsCompleted == null && (c.DueDate.Value.Month == i && c.DueDate.Value.Year == year)
I think this will return results
where (iscompleted is false or iscompleted is null)
and( month and year match)
you could try
(c.IsCompleted == false) || (c.IsCompleted == null && c.DueDate.Value.Month == i && c.DueDate.Value.Year == year)
where iscomplete is false or
( iscomplete is null and month and year match)
Related
I have EF Employee table with fields EmpNo, FirstName, LastName, Email. And to create LINQ to search all columns and return existing record. If one or more fields is null or empty the return result based on existing data. I wrote code:
public static int Search(EmployeeDt emp)
{
using (EF.Model1 context = new EF.Model1)
{
List<string> employee = context.Employees.Where(a => (a.EmpNo == null || a.EmpNo == emp.EmpNo)
&& (b => (b.FirstName == null || b.FirstName == emp.FirstName)
&& (c => (c.LastName == null || c.LastName == emp.LastName)).ToList();
return result;
}
}
But code which I tried to write isn't correct. How to write LINQ for my case?
Thanks.
You don't need reuse a=> in second condition and compare emp.FirstName with null not a variable, change your code to
List<string> employee = context.Employees.Where(a => (emp.FirstName == null || a.FirstName == emp.FirstName)
&& (emp.LastName == null || a.LastName == emp.LastName)
&& (emp.EmpNo == null || a.EmpNo == emp.EmpNo)).ToList()
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();
I have a query
return uow.CustomerRepo
.Get()
.Where
(
c=>
c.Firstname.StartsWith(customerSearch.Initial) &&
c.Surname == customerSearch.Surname &&
c.Email == customerSearch.Email &&
c.Postcode == customerSearch.PostCode
)
Is there a way to skip parts of the query if something in customerSearch is empty?
so I want to skip the part
c.Surname == customerSearch.Surname
if
customerSearch.Surname
Is empty
You can do it with a condition that checks the customerSearch part explicitly:
.Where
(
c=>
(customerSearch.Initial == null || c.Firstname.StartsWith(customerSearch.Initial)) &&
(customerSearch.Surname == null || c.Surname == customerSearch.Surname) &&
(customerSearch.Email == null || c.Email == customerSearch.Email) &&
(customerSearch.PostCode == null || c.Postcode == customerSearch.PostCode)
)
If you need to check for empty strings rather than null, change the condition accordingly.
I have a filter called serviceEntryFilter with a property System which could have values for instance EP1, EP2 OR EP1 and sometimes this filter would be null. If there are multiple values or a single value then the query (IN) clause runs fine . If the filter value is null then I get the following error:
Unable to create a constant value of type 'System.String[]'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.
[HttpPost]
public ActionResult List(string ServiceEntryStatus, string ServiceEntryReconciled, string ServiceEntryReliabilityRecord, string ActiveServiceEntry,
int PageNo, ServiceEntryFilter serviceEntryFilter = null)
{
string[] systems = null;
var list = (from se in db.ServiceEntry
join r in db.RunLogEntry on se.RunLogEntryID equals r.ID into joinRunLogEntry
from r2 in joinRunLogEntry.DefaultIfEmpty()
join u in db.User on se.TechnicianID equals u.ID
join s in db.System1 on se.SystemID equals s.ID
where (
((se.RunLogEntryID == 0 || se.RunLogEntryID != null))
&& ((serviceEntryFilter.ID.HasValue == false) || (se.ID == serviceEntryFilter.ID.Value && serviceEntryFilter.ID.HasValue == true))
&& ((serviceEntryFilter.ServiceDateTime.HasValue == false) || (EntityFunctions.TruncateTime(se.ServiceDateTime) == EntityFunctions.TruncateTime(serviceEntryFilter.ServiceDateTime) && serviceEntryFilter.ServiceDateTime.HasValue == true))
&& ((serviceEntryFilter.RunDate.HasValue == false) || (EntityFunctions.TruncateTime(r2.RunDate) == EntityFunctions.TruncateTime(serviceEntryFilter.RunDate) && serviceEntryFilter.RunDate.HasValue == true))
&& ((serviceEntryFilter.Technician == null) || (u.FullName.Contains(serviceEntryFilter.Technician.Trim()) && serviceEntryFilter.Technician != null))
&& (
((ServiceEntryStatus == "O" && se.ServiceRequestClosed == false) ||
(ServiceEntryStatus == "C" && se.ServiceRequestClosed == true) ||
(ServiceEntryStatus == "A")
)
)
&& (
((ServiceEntryReliabilityRecord == null) ||
(ServiceEntryReliabilityRecord == "N" && se.ReliabilityRecord == false) ||
(ServiceEntryReliabilityRecord == "Y" && se.ReliabilityRecord == true) ||
(ServiceEntryReliabilityRecord == "A")
)
)
&& (
((ServiceEntryReconciled == null) ||
(ServiceEntryReconciled == "N" && se.Reconciled == false) ||
(ServiceEntryReconciled == "Y" && se.Reconciled == true) ||
(ServiceEntryReconciled == "A")
)
)
&& (
((ActiveServiceEntry == null) ||
(ActiveServiceEntry == "N" && se.Active == false) ||
(ActiveServiceEntry == "Y" && se.Active == true) ||
(ActiveServiceEntry == "A")
)
)
&& (
(s.PlatformID == platformID) || (platformID == 0)
)
&& ((serviceEntryFilter.System == null) || ((serviceEntryFilter.System != null) && systems.Contains(s.SystemFullName)))
)
orderby se.ID descending
select new ServiceSearchEntry()
{
ID = se.ID,
ServiceDateTime = se.ServiceDateTime,
Technician = u.FullName,
System = s.SystemFullName,
ReasonForFailure = se.ReasonForFailure,
RunDate = (r2 == null ? (DateTime?)null : r2.RunDate)
});
var listData = list.Skip((page - 1) * PageSize).Take(PageSize);
ServiceEntriesListViewModel viewModel = new ServiceEntriesListViewModel()
{
ServiceSearchEntry = listData,
PagingInfo = new PagingInfo
{
CurrentPage = page,
ItemsPerPage = PageSize,
TotalItems = list.Count()
}
};
}
The Issue:
The following clause is throwing an error when SystemFilter.System is NULL. It is null at times when users do not select values for it. Sample values are as follows:
EP1, EP2
EP1
TP2, TP3, TP4
&& ((serviceEntryFilter.System == null) || ((serviceEntryFilter.System != null) && systems.Contains(s.SystemFullName)))
If it has a value, then I put it in an array and its works like a charm, its just when its null.
The issue is that everything inside a LINQ statement will get translated to SQL. There isn't really a conditional statement that I see here that says "don't try to add this array filter if it's actually null".
I would initialize the systems array to a zero length array, overwrite it if the filter.Systems is not null, and then make my linq statement as follows:
systems.Contains(s.SystemFullName)
Don't include that null checking inside the LINQ statement as it's not doing what you are expecting.
To build conditional LINQ statements, you might want to look at PredicateBuilder: http://www.albahari.com/nutshell/predicatebuilder.aspx
This is a known limitation with Linq to Entities - see section on Referencing Non-Scalar Variables Not Supported.
In otherwords, this line:
systems.Contains(s.SystemFullName)
can't be used as part of your EF query.
Probably something simple, but as I'm new to lambda expressions, the problem evades me:
m => m.contactID == contactID && m.primaryAddress == true && (m.addressTypeID == 2 || m.addressTypeID == 3)
I tried to use that lambda expression but I receive an invalid operator. Is there a way to simplify this so that it would work?
Edit:
The equivolent sql query would be:
SELECT *
FROM Contact
WHERE contactID = 3
AND primaryAddress = 1
AND (addressTypeID = 2 OR addressTypeID = 3)
I have a repository function defined like so:
public E Single(Expression<Func<E, bool>> where)
{
return objectSet.Single<E>(where);
}
I'm passing the lambda expression above into this function:
myRepository.Single(m => m.contactID == contactID && m.primaryAddress == true && (m.addressTypeID == 2 || m.addressTypeID == 3));
If you are receiving an InvalidOperationException, the most likely cause is that there is more than one record that matches your criteria.
Queryable.Single will raise InvalidOperationException if there is more than a single correct value. In this case, try using .First(m => ..) instead:
myRepository.First(m =>
m.contactID == contactID &&
m.primaryAddress == true &&
(m.addressTypeID == 2 || m.addressTypeID == 3)
);
This will return the first matching result, if there are more than one. If you need to handle no matches, look into FirstOrDefault (which will return null if there are no matches).
m.primaryAddress == true looks suspicious. is m.primaryAddress really a bool property?
m => (m.contactID == contactID && m.primaryAddress == true && (m.addressTypeID == 2 || m.addressTypeID == 3)) is merely a boolean expression.
You need to do something like
list.Remove(m => (m.contactID == contactID && m.primaryAddress == true && (m.addressTypeID == 2 || m.addressTypeID == 3))) etc
This says take each item in my list as m if this returns true remove m
Edit OP reposted while I was writing that answer
I would write this like this as to your syntax.
Func Filter<var, bool> = m => (m.contactID == contactID && m.primaryAddress == true && (m.addressTypeID == 2 || m.addressTypeID == 3))
then pass Filter into your myrepository.Single(Filter)
From your SQL query, should it be:
m => m.contactID == contactID && m.primaryAddress == 1 && (m.addressTypeID == 2 || m.addressTypeID == 3)