String to LINQ expression? [duplicate] - c#

This question already has answers here:
Linq - check condition in where clause if field can be null
(3 answers)
Closed 4 years ago.
How can I transform the string with the query in it into an actual LINQ expression so I can execute it?
if(email!= null)
{
query += "x => x.Email.Contains(email)";
}
if (firstname != null)
{
query += "&& x.FirstName.Contains(firstname)";
}
if (lastname != null)
{
query += "&& x.LastName.Contains(lastname)";
}
return context.UserAccounts.Where(query).ToList();

Try this:
<your collection>.
.Where(o => (email!= null)? o.Email.Contains(email) : true).
.Where(o => (firstname != null)? o.FirstName.Contains(firstname) : true).
.Where(o => (lastname != null)? o.LastName.Contains(lastname) : true).
ToList();
Basically it means the filter will apply only when the condition is met (just like in your if sentences).

If the query is required with the combination of where clauses then every time result needs to be saved in query itself
var query = context.UserAccounts;
if(email != null)
{
query = query.Where(x => x.Email.Contains(email));
}
if (firstname != null)
{
query = query.Where(x => x.FirstName.Contains(firstname));
}
if (lastname != null))
{
query = query.Where(x => x.LastName.Contains(lastname));
}
return query.ToList();
Another complex approach could be to use Actions

Instead of saving your query as a string you could save it as an IQueryable (from the System.Linq namespace).
var query = context.UserAccounts;
if(email!= null)
{
query = query.Where(x => x.Email.Contains(email));
}
if (firstname != null)
{
query = query.Where(x => x.FirstName.Contains(firstname));
}
if (lastname != null)
{
query = query.Where(x => x.LastName.Contains(lastname));
}
return query.toList();
When you finally call ToList() the IQueryable is enumerated to a List of UserAccount.

Maybe I'm not seeing your problem correctly so excuse me if i'm wrong.
Why convert the string to a LINQ expression when you can do this:
var query = context.UserAccounts;
if(email != null)
{
query = query.Where(x => x.Email.Contains(email));
}
if (firstname != null)
{
query = query.Where(x.FirstName.Contains(firstname));
}
if (lastname != null))
{
query = query.Where(x.LastName.Contains(lastname));
}
return query.toList();

Related

Calling query inside query in entity framework core

I want to do something like this
public string GetSiteTitleFromChangeHistory(int siteId)
{
var changeHistories = changeHistoryRepository.GetAll(c => c.SiteRegistryId == siteId);
var value = changeHistories.firstOrDefault(r=>r.State="Active")
return value.Title;
}
public IQueryable<PendingReconfirmation> GetSitesForBusinessReconfirmationReminder(IList<StateStatus> stateStatusMappingIds,
string country, int reminderDay)
{
return from reg in repositorySpositeRegistry.GetAll(x => x.SiteUrlcountryCode != null
&& x.SiteUrlcountryCode.ToLower() == country.ToLower())
select new PendingReconfirmation()
{
Id = reg.Id,
SiteTitle = GetSiteTitleFromChangeHistory(reg.Id!).ToString() ?? reg.SiteTitle,
};
}
Repository.GetAll look like this
public IQueryable<T> GetAll(Expression<Func<T, bool>>? filter = null)
{
var query = entities.AsQueryable();
if (filter != null)
query = query.Where(filter);
return query;
}
But I am getting error
The client projection contains a reference to a constant expression of '' through the instance method 'GetSiteTitleFromChangeHistory'. This could potentially cause a memory leak; consider making the method static so that it does not capture constant in the instance.
Any help will be highly appreciated
Make this function GetSiteTitleFromChangeHistory as STATIC.
Is there a specific reason you split up GetSiteTitleFromChangeHistory into a separate method?
Otherwise you should be able to do a subquery like so, provided the queryable used for the subquery is based on a dbset in the same efcontext:
public IQueryable<PendingReconfirmation> GetSitesForBusinessReconfirmationReminder(IList<StateStatus> stateStatusMappingIds,
string country, int reminderDay)
{
return from reg in repositorySpositeRegistry.GetAll(x => x.SiteUrlcountryCode != null
&& x.SiteUrlcountryCode.ToLower() == country.ToLower())
select new PendingReconfirmation()
{
Id = reg.Id,
SiteTitle = changeHistoryRepository.GetAll(c => c.SiteRegistryId == reg.Id && c.State == "Active").FirstOrDefault().Title ?? reg.Title
};
}

Linq to SQL - Ignore search parameters that are null or zero

I have a search form where the user can enter one to many parameters (Data, Status, Type, ID, Summary, Description) and leave the rest blank.
Here's my Linq to SQL code for my basic search. Is there a way to check each parameter within the Linq for zero, null or empty string?
List<RequestStatusModel> objRequestStatus = new List<RequestStatusModel>();
var query = from r in SimCareDB.Requests
where r.CustomerID == 31
select (new RequestStatusModel
{
RequestID = r.RequestID,
RequestTitle = r.RequestTitle,
DateAdded = r.DateAdded.ToString(),
DateChanged = r.DateChanged.ToString(),
RequestStatusID = r.StatusID
});
Thank you!
If it doesn't have to be in your linq statement you could just do it with classic if statements.
List<RequestStatusModel> objRequestStatus = new List<RequestStatusModel>();
var query = from r in SimCareDB.Requests
where r.CustomerID == 31
select (new RequestStatusModel
{
//...
});
if(data != null) //Replace with additional checks, if neccessary
{
query = query.where(x=> ...);
}
if(status != null)
{
query = query.where(x => ...)
}
If you want to only filter if certain criteria is passed, you should do something like this
var objRequestStatus = new List<RequestStatusModel>();
var query = from r in SimCareDB.Requests
where r.CustomerID == 31
if (String.IsNullOrEmpty(r.RequestID))
objRequestStatus = objRequestStatus.Where(x => x.RequestID == r.RequestID);
if (String.IsNullOrEmpty(r.RequestTitle))
objRequestStatus = objRequestStatus.Where(x => x.RequestTitle == r.RequestTitle);
//you other filters here
This sets up the expression to what you want based on which requests are passed
If you want to avoid all those ifs, you could do
List<RequestStatusModel> objRequestStatus = new List<RequestStatusModel>();
var query = from r in SimCareDB.Requests
where (r.CustomerID == 31) &&
(!String.IsNullOrEmpty(id) ? r.RequestID == id : true) &&
(!String.IsNullOrEmpty(status) ? r.StatusID == status : true)
/* And so on */
select (new RequestStatusModel
{
RequestID = r.RequestID,
RequestTitle = r.RequestTitle,
DateAdded = r.DateAdded.ToString(),
DateChanged = r.DateChanged.ToString(),
RequestStatusID = r.StatusID
});

Dynamic Where clause with unknown number of parameters

I have searched for an answer to my question, but have been unable to find one that meets my needs.
The following two code snippets return the same thing and I have no preference which one to use, I am just including both in case it helps someone answer my question
private List<MyClass> GetMyClass(string name, string city, string state, string zip)
{
using (MyEntities ctx = new MyEntities())
{
var results = from a in ctx.MyEntity
where (a.Name == name &&
a.City == city &&
a.State == state &&
a.ZIP == zip)
select a;
return results.ToList();
}
}
private List<MyClass> GetMyClass(string name, string city, string state, string zip)
{
using (MyEntities ctx = new MyEntities())
{
var results = ctx.MyEntity.Where(a => a.Name == name)
.Where(a => a.City == city)
.Where(a => a.State == state)
.Where(a => a.ZIP == zip)
.Select(a => a);
return results.ToList();
}
}
For the purposes of this example, let's say I have a search screen which requires users to enter a Name and a City; State and ZIP are optional. The query must at least search by those two fields, and any additional fields, if necessary.
Obviously, with my above examples, if a user searches only by Name and City, they would not get any results as the queries would be trying to match State == null and ZIP == null since those two parameters where not supplied.
How can I rewrite this code to only search on the fields that parameters have been supplied for?
You could just chain them, something like:
var results = ctx.MyEntity.AsQueryable();
if(name != null)
results = results.Where(a => a.Name == name);
// ... snip ...
if(zip != null)
results = results.Where(a => a.ZIP == zip)
return results.ToList();
var results = from a in ctx.MyEntity
where ((a.Name == name || name == null) &&
(a.City == city || city == null) &&
(a.State == state || state == null) &&
(a.ZIP == zip) || zip == null)
select a;

Multimode Search in Entity Framework

The code is listed below , is my code for multimode search in ado.net , i use now entity framework and i dont know how write this perfectly with less code
string query = '"SELECT id From user";
if(filter1 != "" || filter2 != "")
{
query += "where ";
}
if(filter1 != "")
{
query += "name='" + filter1 + "'";
if(filter2 != "")
query += " and "
}
if(filter2 != "")
query += "name" + filter2;
Try this:
var result = (from s in db.user
select s).AsQueryable();
if (filter1 != "")
{
result = result.Where(x=>x.name == filter1);
}
if (filter2 != "")
{
result = result.Where(x=>x.name == filter2);
}
var output = result.ToList();
Sample:
YourIQueryableResults.Where(x => filter1!="" && (x.Name == filter1))
or
if (filter1!="") { YourIQueryableResults = YourIQueryableResults.Where(x => x.Name == filter1)}

How can i cast IQueryable<> query to IQueryable<obj.getType()>?

How can i factorize this code?
my filter returns several type of document. the difficult is that i have some query per type... i would like a generic method to return a correct query
thanks
if(this.comboBoxType.Text.Equals("Vente"))
{
IQueryable<Vente> queryV = ContexteDAO.ContexteDonnees.Vente
.Include("Client")
.Include("Paiement")
.Include("Employe").OrderBy(v => v.venteID);
if (this.tbxNomCli.Text != "")
queryV = queryV.Where(v => v.Client.nom.Contains(this.tbxNomCli.Text));
if (this.comboBoxEtat.Text != "Tous")
queryV = queryV.Where(v => v.etat == this.comboBoxEtat.Text);
if (this.checkBoxDate.Checked)
queryV = queryV.Where(v => v.date.Equals(this.dateTimePicker.Value.Date));
if (this.tbxTva.Text != "")
queryV = queryV.Where(v => v.Client.numEntreprise.Contains(this.tbxTva.Text));
if (this.checkBoxVendeur.Checked)
{
Employe employe = this.comboBoxVendeur.SelectedItem as Employe;
queryV = queryV.Where(v => v.Employe.login.Equals(employe.login));
}
this.documentBindingSource.DataSource = queryV.ToList();
}
if (this.comboBoxType.Text.Equals("Commande"))
{
IQueryable<Commande> queryC = ContexteDAO.ContexteDonnees.Commande
.Include("Client")
.Include("Paiement")
.Include("Employe").OrderBy(c => c.commandeID);
if (this.tbxNomCli.Text != "")
queryC = queryC.Where(v => v.Client.nom.Contains(this.tbxNomCli.Text));
if (this.comboBoxEtat.Text != "Tous")
queryC = queryC.Where(v => v.etat == this.comboBoxEtat.Text);
if (this.checkBoxDate.Checked)
queryC = queryC.Where(v => v.date.Equals(this.dateTimePicker.Value.Date));
if (this.tbxTva.Text != "")
queryC = queryC.Where(v => v.Client.numEntreprise.Contains(this.tbxTva.Text));
if (this.checkBoxVendeur.Checked)
{
Employe employe = this.comboBoxVendeur.SelectedItem as Employe;
queryC = queryC.Where(v => v.Employe.login.Equals(employe.login));
}
this.documentBindingSource.DataSource = queryC.ToList();
}
You could make a generic approach:
public IQueryable<T> GetData<T>( string identifier )
{
switch( identifier )
{
case "Vente":
{
return ContexteDAO.ContexteDonnees.Vente
.Include("Client")
.Include("Paiement")
.Include("Employe")
.OrderBy(v => v.venteID);
// do more stuff
break;
}
// add more cases
default:
{
return null;
}
}
}
the call would look like:
IQueryable<Vente> result = GetData<Vente>( "Vente" );
it would solve your problem but i won't like it, because you need to specify the type AND need an identifier which selection you would like to perform. This could lead to an exception really fast when you have something like GetData<Vente>( "OtherEntity" ).

Categories

Resources