Linq query to check for duplicate values - c#

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

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.

Using Linq to filter by List<ListItem>

I am trying to extend my linq query with additional search criteria to filter the data by sending also a List<Listitem> to the function for processing. The List can contain 1 or more items and the objective is to retreive all items which match any criteria.
Since i am sending several search criteria to the function the goal is to make a more accurate filter result the more information i am sending to the filter. If one or several criterias are empty then the filter will get less accurate results.
Exception is raised every time i execute following code, and I cant figure out how to solve the using statement to include the List<ListItem>. Appreciate all the help in advance!
Exception: Unable to create a constant value of type 'System.Web.UI.WebControls.ListItem'. Only primitive types or enumeration types are supported in this context.
using (var db = new DL.ENTS())
{
List<DL.PRODUCTS> products =
(from a in db.PRODUCTS
where (description == null || description == "" ||
a.DESCRIPTION.Contains(description)) &&
(active == null || active == "" || a.ACTIVE.Equals(active, StringComparison.CurrentCultureIgnoreCase)) &&
(mID == null || mID == "" || a.MEDIA_ID == mID) &&
(mID == null || objTypes.Any(s => s.Value == a.OBJECTS)) //Exception here!
select a).ToList<DL.PRODUCTS>();
return products;
}
Pass collection of primitive values to expression:
using (var db = new DL.ENTS())
{
var values = objTypes.Select(s => s.Value).ToArray();
List<DL.PRODUCTS> products =
(from a in db.PRODUCTS
where (description == null || description == "" || a.DESCRIPTION.Contains(description)) &&
(active == null || active == "" || a.ACTIVE.Equals(active, StringComparison.CurrentCultureIgnoreCase)) &&
(mID == null || mID == "" || a.MEDIA_ID == mID) &&
(mID == null || values.Contains(a.OBJECTS))
select a).ToList<DL.PRODUCTS>();
return products;
}
That will generate SQL IN clause.
Note - you can use lambda syntax to compose query by adding filters based on some conditions:
var products = db.PRODUCTS;
if (!String.IsNullOrEmpty(description))
products = products.Where(p => p.DESCRIPTION.Contains(description));
if (!String.IsNullOrEmpty(active))
products = products.Where(p => p.ACTIVE.Equals(active, StringComparison.CurrentCultureIgnoreCase)));
if (!String.IsNullOrEmpty(mID))
products = products.Where(p => p.MEDIA_ID == mID);
if (mID != null)
products = products.Where(p => values.Contains(p.OBJECTS));
return products.ToList();
Linq isn't able to convert the predicate on ListItem to something useful to Sql.
I would suggest that you pre-project the values of the ListItems into a simple List<string> before using this with Contains (which is converted to IN)
var listValues = objTypes.Select(_ => _.Value).ToList();
List<DL.PRODUCTS> products = ...
listValues.Contains(a.OBJECTS))

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