LINQ OR operator not giving result - c#

I have written a LINQ query with or condition in it, but its not working, it seem I am doing something wrong.
I am passing a string value and on it, I want to get my result.
var userDetails = context.tbl_members.Where
(
d => d.Mobile == value
||
d.MemberId == Int32.Parse(value)
).SingleOrDefault();
its not working if someone put a mobile no, but if work with memberID
if I split the query keep only mobile no its running fine.
var userDetails = context.tbl_members.Where(d => d.Mobile == value ).SingleOrDefault();
Please check what I did wrong with or condition
Regards
Moksha

var userDetails = context.tbl_members
.Where(d => d.Mobile == value ||
d.MemberId == Int32.Parse(value))
.SingleOrDefault();
It looks like you are using Linq to Entities or Linq to Sql. Int32.Parse() is not supported in that context - just do the number conversion before your query:
int numValue = Int32.Parse(value);
var userDetails = context.tbl_members
.Where(d => d.Mobile == value || d.MemberId == numValue)
.SingleOrDefault();

thanks for your help brokenGlass,
the error was in converting from string to int, as I was passing string of 10 digits, it was not getting converted into int
Value was either too large or too small for an Int32.
thanks

Related

C# LINQ DataTime List

Have a some problem with converting to List
public List<DateTime> findDateBetween(DateTime start,DateTime end)
{
var query = from entry in sd.gw_chemistry
where (entry.insert_datetime >=start & entry.insert_datetime<=end & a == entry.well_id & b == entry.indicator_id)
select entry.insert_datetime;
return (List<DateTime>)query;
}`
Error:
System.InvalidCastException: Unable to cast object of type "System.Data.Objects.ObjectQuery1[System.Nullable1[System.DateTime]]" to type "System.Collections.Generic.List`1[System.DateTime]".
There are a number of problems with your code.
Your query is selecting elements of type DateTime? (or Nullable<DateTime>). You will need to decide what you want to do if a date is null. Exclude it from the results? Return a default value? If you can be sure it will never be null, you can select entry.insert_datetime.Value.
Your query does not return a list, you will have to convert it to a list using ToList().
For the conditional AND operator (&&) it appears you are using &.
You are using variables a and b that do not seem to be defined anywhere (unless they are member variables).
So assuming that a and b are member variables, and an insert_datetime is never null you can do:
return sd.gw_chemistry
.Where(e =>
e.insert_datetime >= start && e.insert_datetime <= end &&
a == entry.well_id && b == entry.indicator_id)
.Select(e => e.insert_datetime.Value)
.ToList();
As the error is trying to tell you, that isn't a List<T>, and you can't cast it to a type that it isn't.
You can create a List<T> from your query by calling .ToList().
public List<DateTime> findDateBetween(DateTime start,DateTime end)
{var query = from entry in sd.gw_chemistry
where (entry.insert_datetime >=start & entry.insert_datetime<=end & a == entry.well_id & b == entry.indicator_id)
select entry.insert_datetime;
return query.ToList();}
Nothing serious here. You just need to call ToList() on your query. However I do see the usage of & instead of && as a serious problem.
Correct code should look like:
public List<DateTime> findDateBetween(DateTime start,DateTime end)
{
var query =
from entry in sd.gw_chemistry
where (entry.insert_datetime >=start &&
entry.insert_datetime<=end &&
a == entry.well_id &&
b == entry.indicator_id)
select entry.insert_datetime.Value;
return query.ToList();
}`

LINQ and C# - Dealing with a potentially null parameter

I am relatively new to LINQ but looking for some "best practice" advice on how to deal with the following. I know there are many ways to deal with this, but looking to see how more experienced people would write the code.
My LINQ at present:
var company = (from c in db.RPTINQUIRies
where c.CONCOM == concom && c.LOPER == engineer
orderby c.CREATION_DATE descending
select c);
Now the ActionResult parameter that is being passed in here (engineer) may or may not be empty. Where it is empty, I essentially want to remove the && C.LOPER == engineer clause all together.
What's the best way to deal with this?
It sounds like you just want:
where c.CONCOM == concom && (engineer == null || c.LOPER == engineer)
Alternatively, you could build up the query step by step:
var query = db.RPTINQUIRies.Where(c => c.CONCOM == concom);
if (engineer != null)
{
query = query.Where(c => c.LOPER == engineer);
}
query = query.OrderByDescending(c => c.CREATION_DATE);

Only do Where condition if a value is passed in

I have the following LINQ statement that does on where on the date and a LabID.
I'm passing in a list of LABS and a date, however they are not required, and I could potentially only pass in a date, and no lab, in which case I'd like to get results for all labs for that particular lab.
here is what I have now:
List<dExp> lstDatExp = (from l in ctx.dExp.Include("datLab")
where values.Contains(l.datL.Lab_ID)
&& l.reportingPeriod == reportingPeriod
select l).ToList<dExp>();
But this breaks if the value getting passed in is not there. How do I change this to make sure both of my where statements are optional?
With IQueryable you can simply add conditions in steps:
int? reportingPeriod = ...;
IQueryable<dExp> resultsQuery = // don't use `var` here.
ctx.dExp.Include("datLab");
if (values != null)
resultsQuery = resultsQuery.Where(exp => values.Contains(exp.datL.Lab_ID));
if (reportingPeriod.Hasvalue)
resultsQuery = resultsQuery.Where(exp => exp.reportingPeriod == reportingPeriod.Value);
// additional .Where(), .OrderBy(), .Take(), .Skip() and .Select()
// The SQL query is made and executed on the line below
// inspect the string value in the debugger
List<dExp> results = resultsQuery.ToList();
Here are two ways to do that.
But first, please don't use a single lowercase l as an identifier. It is way too easy to confuse it with the number 1. More generally, stp using abbrevs in yr cde, it mks it hrdr to rd.
First technique:
var query = from lab in ctx.dExp.Include("datLab")
where values == null || values.Contains(lab.datL.Lab_ID)
where reportingPeriod == null || lab.reportingPeriod == reportingPeriod
select lab;
var list = query.ToList<dExp>();
Second technique:
IEnumerable<dExp> query = ctx.dExp.Include("datLab");
if (values != null)
query = query.Where(lab=>values.Contains(lab.datL.Lab_ID));
if (reportingPeriod != null)
query = query.Where(lab=>lab.reportingPeriod == reportingPeriod);
var list = query.ToList<dExp>();
What we do is something like (l.reportingPeriod == reportingPeriod || reportingPeriod == null) So you check to see if the parameter is its default meaning it hasnt been used or if there is something there check it against the database.
You need to check if your values are null before doing the query, and if they are, don't do the extra condition.
List<dExp> lstDatExp =
(from l in ctx.dExp.Include("datLab")
where
(values == null || values.Contains(l.datL.Lab_ID)) &&
(reportingPeriod == null || l.reportingPeriod == reportingPeriod)
select l).ToList<dExp>();
This way if values or reportingPeriod are null they are essentially optional.

Get a single string from a LINQ to XML query

Here is what I want to do:
string parseCode = from x in xml.Descendants("LogType")
where x.Attribute("ID").Value == string)ddlHistoryLogDefinitions.SelectedValue
select x.Attribute("ParseCode").Value;
But that gives error: "Cannot implicitly convert type 'System.Collections.Generic.IEnumerable' to 'string'"
There will only be one value for x.Attribute("ParseCode") but it insists on returning type IEnumerable<string>. How can I extract that value into a string ?
EDIT: Thank you for your responses. Here is what worked for me:
string parseCode = (from x in xml.Descendants("LogType")
where x.Attribute("ID").Value == (string) ddlHistoryLogDefinitions.SelectedValue
select (string) x.Attribute("ParseCode").Value).FirstOrDefault();
This trick was wrapping the entire linq query in () before the .FirstOrDefault().
Use .Single to select the only result if you know there will be one and only one:
string parseCode = (from x in xml.Descendants("LogType")
where x.Attribute("ID").Value == string)ddlHistoryLogDefinitions.SelectedValue
select x.Attribute("ParseCode").Value).Single();
Use .SingleOrDefault or .First If there might be none or more then one respectively.
You query returns a collection. If you need the first found LogType node, then you can do something like this:
string parseCode = xml.Descendants("LogType")
.Where(x => x.Attribute("ID").Value == (string)ddlHistoryLogDefinitions.SelectedValue)
.Select(arg => x.Attribute("ParseCode").Value)
.FirstOrDefault();
Will return null if no element found.

Multiple WHERE's in same LINQ 2 SQL Method

I have the below LINQ Method I am trying to create. The issue seems to be the Second WHERE clause. I am getting this error -->
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<MatrixReloaded.Data.CMO.tblWorkerHistory>' to 'bool'
I also had && there vs WHERE but I was getting a similar error. I don't NEED anything from tblWorkerHistories except the EndDate stuff.
There is a Many To Many relationship between the 2 tables with EnrollmentID being a FK on both.
public static DataTable GetCurrentWorkersByEnrollmentID(int enrollmentID)
{
using (var context = CmoDataContext.Create())
{
context.Log = Console.Out;
var currentWorkers = from enrollment in context.tblCMOEnrollments
where enrollment.EnrollmentID == enrollmentID
where enrollment.tblWorkerHistories.Where(a => a.EndDate == null || a.EndDate > DateTime.Now)
select
new
{
enrollment.CMONurseID,
enrollment.CMOSocialWorkerID,
SupportWorkerName = enrollment.tblSupportWorker.FirstName + " " + enrollment.tblSupportWorker.LastName,
SupportWorkerPhone = enrollment.tblSupportWorker.Phone
};
return currentWorkers.CopyLinqToDataTable();
}
}
This is the problem:
where enrollment.tblWorkerHistories.Where(/* stuff */)
Where returns a sequence... whereas you need something that will return a Boolean value. What are you trying to do with that embedded Where clause?
As Marc says, it could be that you just need an Any call instead of Where... but if you could explain what you're trying to do, that would make it a lot easier to help you. Note that Any does return a Boolean value, instead of a sequence.
EDIT: Okay, so in SQL you'd use a join, but you don't need an explicit join here because LINQ is implicitly doing that for you, right? If you're trying to find enrollments where any of the histories match the date, and you don't care about the histories themselves, then Any is indeed what you want:
var currentWorkers = from enrollment in context.tblCMOEnrollments
where enrollment.EnrollmentID == enrollmentID
where enrollment.tblWorkerHistories.Any
(a => a.EndDate == null || a.EndDate > DateTime.Now)
select ...
I suspect you mean .Any instead of .Where in the sub-query; the outermost .Where (i.e. the second where) expects a predicate expression, but yours is currently a selector - try:
where enrollment.tblWorkerHistories.Any(
a => a.EndDate == null || a.EndDate > DateTime.Now)

Categories

Resources