Alternative of ElementAtOrDefault() in Linq to Sql - c#

I want to run the following query but it says that ElementAt is not supported.
List<Road> rdExist = (from u in db.Roads where (u.GPScoordinates.ElementAtOrDefault(0).Latitude == lattitude1 && u.GPScoordinates.ElementAtOrDefault(0).Longitude == longitude1) && (u.GPScoordinates.ElementAtOrDefault(1).Latitude == lattitude2 && u.GPScoordinates.ElementAtOrDefault(1).Longitude == longitude2) select u).ToList();
Can anybody please suggest an alternative to this. I can't figure out any myself. FirstOrDefault works fine but it can't help me in this query.

Try Skip(n).FirstOrDefault() in place of ElementAtOrDefault(n). That basically means "get the first element after skipping n elements", which about the same as "get element at position n" where in the latter case n starts from 0 :
List<Road> rdExist = (from u in db.Roads
where (u.GPScoordinates
.FirstOrDefault().Latitude == lattitude1 &&
u.GPScoordinates
.FirstOrDefault().Longitude == longitude1) &&
(u.GPScoordinates
.Skip(1).FirstOrDefault().Latitude == lattitude2 &&
u.GPScoordinates
.Skip(1).FirstOrDefault().Longitude == longitude2)
select u).ToList();

You can use Skip & FirstOrDefault:-
List<Road> rdExist = (from u in db.Roads where
(u.GPScoordinates.FirstOrDefault().Latitude == lattitude1 &&
u.GPScoordinates.FirstOrDefault().Longitude == longitude1) &&
(u.GPScoordinates.Skip(1).FirstOrDefault().Latitude == lattitude2 &&
u.GPScoordinates.Skip(1).FirstOrDefault().Longitude == longitude2) select u).ToList();
ElementAtOrDefault is not supported by LINQ-SQL. Check this.
Also, please be careful while using this query as it may result in Null reference exception in case of default values. So, better check for nulls before retrieving values.

Related

EF6 Get Record where info from two different tables equal x

I am guessing this is a JOIN issue - which I don't understand anyway.
but I have to get a Record from EUReporteds if the Where clause is correct and if the Where clause on another table is NOT correct.
The coding I am using is truly horrific
do
{
// Get the next Unprocessed.
if (skip == 0)
eur = de.EUReporteds.Where(r => r.Processed == false && r.ReportProcessingCount < 11).FirstOrDefault();
else
eur = de.EUReporteds.Where(r => r.Processed == false && r.ReportProcessingCount < 11).OrderBy(ob => ob.id).Skip(skip).FirstOrDefault();
// Have we personally already done this?
pr = de.ProcessingResults.Where(p => p.UserId == CurrentUser.UserId && p.id == eur.id).FirstOrDefault();
skip++;
} while (pr != null || eur == null); // If so repeat
So what I am trying to do here is:
Get a record from EUReporteds
WHERE the record has not been processed
AND WHERE the RecordProcessingCount is less than 11
Check to see if this logged in user has already processed that record by
Getting The ProcessingResults Record where The CurrentUser exists
AND WHERE the ID of EUReporteds also exists
IF ProcessingResults Record Exists then we have done this record find the next until The ProcessingResults record can not be found.
Could someone please show me how to write this properly please.
Try this(using linq):
var firstUnprocessedRecord = (from eur in de.EUReporteds
where !eur.Processed && eur.ReportProcessingCount < 11
&& !(de.ProcessingResults.Any(o=>o.UserId == CurrentUser.UserId && o.id == eur.id))
orderby eur.id
select eur).FirstOrDefault();

A method that searches for entities, a certain property of which matches a given criteria in Entity Framework

Okay, I'm not sure whether the title of the question is clear enough, but I couldn't think of a simpler explanation in one sentence.
I'm making a search page for a ASP.NET web application. I want to allow the users to search using different filters.
I came up with a method that filters the Publications (these are the entities that the user will retrieve) based on the type of Categories that the user has chosen.
List<Publication> publications =
(from p in GetPublications()
where categories.Contains((int)p.CategoryId)
select p).ToList();
The above linq query is equivalent to the following sql one:
select * from Publication p where p.CategoryId in (#chosenCategoryIds)
Everything works perfect but the problem is that I want to allow the user to choose from more filters, for example, not only categories, but users, tags, titles and etc.
So, if I want this, I should make a lot of conditional statements checking whether the user has provided given filters or not, something like:
if (categories != null)
{
var publications = (from p in GetPublications()
where categories.Contains((int)p.CategoryId)
select p).ToList();
if (users != null)
{
publications = (from p in publications
where users.Contains((int)p.UserId)
select p).ToList();
}
}
else
{
// Handle other situations..
}
So, it turns out that I'm doing basically one and the same thing for different filters. My question is whether somebody knows or can think of a better way to achieve this? If not, let's take a look at the following method:
public List<InterpretumDAL.Publication> FilterPublications(List<InterpretumDAL.Publication> oldList, int[] values)
{
List<InterpretumDAL.Publication> newList =
(from p in oldList
where values.Contains((int)p.CategoryId)
select p).ToList();
return newList;
}
What I try to achieve with the method above is to filter a given list by a given array of values. The thing is that I don't know how to tell the method which property to compare, so I can call it something like this:
newList = FilterPublications(publications, categories, CATEGORY_PROPERTY_OF_PUBLICATION);
newList = FilterPublications(publications, users, USER_PROPERTY_OF_PUBLICATION);
newList = FilterPublications(publications, tags, TAG_PROPERTY_OF_PUBLICATION);
Edit:
According to LiquidPony's answer I did it this way:
var publications = (from p in GetPublications()
where (
(categories == null || categories.Length == 0 || (p.CategoryId.HasValue && categories.Contains((int)p.CategoryId)))
&& (users == null || users.Length == 0 || users.Contains(p.UserId))
&& (tags == null || tags.Length == 0 || tags.Contains(p.TagId))
)
select p).ToList();
Taking LiquidPony's answer, I think it would be better to do it like this by using ternary operators.
var query = from p in GetPublications()
where (
(categories != null ? categories.Contains((int)p.CategoryId) : true)
&& (users != null ? users.Contains((int)p.UserId) : true)
&& (tags != null ? tags.Contains((int)p.TagId) : true)
) select p;
If one of the variables isn't provided, that statement will simply evaluate to true and not be included in the SQL evaluation (as far as I know).
You want to avoid using OR's unless absolutely necessary. They are quite inefficient in SQL, and you can usually always find an alternative to get what you want without using them.
The simplest way would be to do something like this:
var query = from p in GetPublications()
where (
(categories == null || categories.Contains((int)p.CategoryId))
&& (users == null || users.Contains((int)p.UserId))
&& (tags == null || tags.Contains((int)p.TagId))
) select p;
That would work if you want to match all criteria. You can switch the && to || if you want to return entities which only match one criteria.

Linq query to check for duplicate values

In one of my pages I need to check if the entered information about a customer consists duplicate PAN NO,Email,Mobile No which may have been entered previously.Currently I am trying it using this Linq To SQL statement
var duplicate = (from dup in dt.Data_Customer_Logs
where dup.cPanGirNo == panno
|| dup.cEmail == email
|| dup.nMobileNo.ToString() == mobno
select dup).Any();
It is working but can anyone help me as to what is the correct method to solve my issue.Also if there are no records found what would be the result.
Any suggestions are welcome.
bool duplicateExists = dt.Data_Customer_Logs.Any(x =>
x.cPanGirNo == panno
|| x.cEmail == email
|| x.nMobileNo.ToString() == mobno);
This is a tad cleaner if you just want to know if such records exist or not. And I think it will avoid bringing back multiple records to the client side and then doing IEnumerable<T>.Any on the results.
If you need to also get back the records that match the criteria, you can use IQueryable<T>.Where:
var duplicates = dt.Data_Customer_Logs.Where(x =>
x.cPanGirNo == panno
|| x.cEmail == email
|| x.nMobileNo.ToString() == mobno);
if(duplicates.Any())
{
// use duplicates...
foreach(var dup in duplicates)
{
//use dup.cEmail, dup.nMobileNo, etc.
try this
var duplicate = (from dup in dt.Data_Customer_Logs
where dup.cPanGirNo == panno
|| dup.cEmail == email
|| dup.nMobileNo.ToString() == mobno
select dup).FirstOrDefault();
if(duplicate != null && duplicate.Any())
//here logic of what should happend if there is something in db

How do you findIndex with conditionals like &&

Let's say you have a List l_mur = new List();
And you populate the list.
Then based on conditions you want to REMOVE some values without requerying...
l_mur.RemoveAt(l_mur.FindIndex(f => (f.xid == tmur.xid && f.sid == tmur.sid && f.mid == tmur.mid && f.bid == tmur.bid)));
However, the code I used here, does not seem to work. It tells me index out of range, but how can it be out of range if I am just searching for something that truly does exist.
List<T>.FindIndex() returns -1 in case there is no match found - which is out of range for List<T>.RemoveAt().
Also note that FindIndex() only returns the index of the first occurrence based on your predicate - if there is more than one match you will only be able to delete the first one of them with your current approach.
A better approach to delete in place based on a predicate would be RemoveAll():
l_mur.RemoveAll(f => (f.xid == tmur.xid && f.sid == tmur.sid && f.mid == tmur.mid && f.bid == tmur.bid));
May be a good idea is to filter the list to a new instance of the list:
var l_mur = l_mur.Where(f => (f.xid != tmur.xid || f.sid != tmur.sid || f.mid != tmur.mid || f.bid != tmur.bid));
Use this code:
l_mur.Remove(l_mur.Find(f => (f.xid == tmur.xid && f.sid == tmur.sid && f.mid == tmur.mid && f.bid == tmur.bid)));

how to combine textbox values in a linq query?

I have a page in which I have several textboxes in order to search depending the value of the textboxes,If I make the search eith only one value everithing works fine but if I try to combine 2 or more values I only get the result of the last textbox.
Here's my query hope you could help me.
var query = from m in SolContext.Menores
where ((m.Solicitud.fiIdSolicitud == rdTxtFolio.Value) || (m.Solicitud.fiAnioSolicitud == rdTxtAnioFolio.Value)
|| (m.Solicitud.CTEdoSolicitud.fcDescEdoSol == status) || (m.Solicitud.fiCircuito == cto) || (m.Solicitud.fiCiudad == cd)
|| (m.Solicitud.fcCveAdsc == adsc) || (m.Solicitud.fiExpEmpleado == rdTxtExp.Value) || (m.Solicitud.fcNomEmpleado == rdTxtNom.Text)
|| (m.Solicitud.fcPatEmpleado == rdTxtAPat.Text) || (m.Solicitud.fcMatEmpleado == rdTxtAMat.Text) || (m.fcPatMenor == rdTxtAPatMenor.Text)
|| (m.fcMatMenor == rdTxtAmatMenor.Text) || (m.fcNomMenor == rdTxtNomMenor.Text) || (m.fiSexoMenor == sexo) || (m.fiAnosMenor == rdTxtAniosMenor.Value) || (m.fiMesesMenor == rdTxtMesMenor.Value))
select m;
rgSolic.DataSource = query;
rgSolic.Rebind();
My guess is that the result of the first textbox is included in the result of the second one.
My guess is that you're using or. The first textbox that matches your value will end your search. If you want to check if it matches all your values, use and.
If that doesn't solve it, we'll need more info.

Categories