I have a long LinqtoSQl query in which several parameters I'm not forcing the user to specify anything. I started using a Select Case statement that would test rather or not a parameter string's length > 0 or if it's an int > 0. But I realized that I would have to test for each possibility and create queries based on each.
I did some searching and ran across a post in which the person answering the post was saying to negate a portion of the query use ||. After doing some more searching (and realizing with little c# skills I do have || is the OR conditional), I realized that wouldn't help me.
I guess what I want to do is something like
Dim r = From x in db.List _
(if firstName.Length < 1 then ignore query
else)where x.firstName = firstName _
(if lastName.Length < 1 then ignore query
else)where x.LastName = lastName _
Select x
I knw there has to be a better way than IfElse'ing my way through this...I was about to do some funky stuff with a StringBuilder, but I'm not sure it would "fire", ie:
Dim sb as New StringBuilder
sb.Append("Dim r = From x in db.List _")
If firstName.Length < 1 then
sb.Append("Where x.firstName = firstName")
ughh, please tell me there's a better way...
Thanks for your help!
Use the fact that queries are composable. I'll write this in C# to start with, then translate it into VB afterwards if you need that. The principle would be the same.
IQueryable<YourEntityType> query = db.List;
if (firstName != "")
{
query = query.Where(x => x.firstName == firstName)
}
if (lastName != "")
{
query = query.Where(x => x.lastName == lastName)
}
Now just read from query appropriately. (I've changed the nature of the string conditions just because it simpler to understand "is this string the empty string" than "is this string's length greater than 0" - both will work, obviously.)
Note that you can't do this sort of conditional call in a query expression, but it's easy when you're just calling the extension methods explicitly.
How about...
Dim r = From x in db.List _
where (x.firstName = firstName Or firstName = "") _
And (x.LastName = lastName Or lastName = "") _
Select x
Related
I have a working query as below:
var result = from sch in schemeDashboard
join exp in Expenditure on sch.schemeId equals exp.SchemeCode
into SchExpGroup
where sch.SectorDepartmentId == selectedDepartmentId &&
sch.YearCode == StateManager.CurrentYear
orderby sch.ADPId
select new
{
ProjectName = sch.schemeName,
ADPNo = sch.ADPId,
Allocation = sch.CurrentAllocation,
Expenditures = from expend in SchExpGroup
where expend.YearCode == StateManager.CurrentYear &&
expend.DepartmentId == selectedDepartmentId &&
InvStatus.Contains(expend.Status)
orderby expend.ADPId
group expend by expend.InvoiceId
};
Now I need to declare "result" as: System.Linq.IQueryable<...> result = null; so that I can write the query in various If-else blocks with minor modification. (projectName is string, ADPNo is int, Allocation is decimal).
I have tried as follow:
System.Linq.IQueryable<string, int, decimal,
System.Collections.Generic.IEnumerable<System.Linq.IGrouping<string, Expenditure>>> result = null;
But this is giving error as: The non-generic type 'IQueryable' cannot be used with typed arguments.
Can anyone point me in right direction? thanx.
The most generical class of C# is the class object. So you can declare your list with the Object type.
IQueryable <object> result = null;
Well I hope it works for you as it worked for me.
I have a Oracle query and would like to transform into Marklogic cts query. It looks like Marklogic CTS doesn't allow to have "and-query" inside of "and-query". I am not sure how Marklogic works. Thanks in advance.
Where clause query:
where (collection = "TRBA" AND fulltext = 1
AND (dnta = "Briefing" OR dnta = "Conference" OR snta = "Workshop"
OR snta = "Published in" AND (snta = "this article" OR dnta = "Journal")
)
AND (cand IN ("Research","Development Center") OR scn IN("424778","98814","393825"))
Translate into Marklogic:
let $uris:= cts:uris(
(),
(),
cts:and-query((
cts:collection-query("/dbs/"TRBA"),
cts:element-value-query(xs:QName("meta:FullTextExists"),"1"),
cts:field-word-query("dnta",("briefing","conference")),
cts:or-query((
cts:element-word-query(xs:QName("meta:snta"),("this article")),
cts:field-word-query("dnta",("Journal")),
cts:and-query((
cts:or-query((
cts:field-word-query("cand", ("Research","Development Center"))
cts:field-word-query("scn",("424778","98814","393825"))
))
))(:inside and-query:)
))(:or-query:)
))(:outside and-query:)
return fn:doc($uris)
There are basic syntax errors in your code above: missing parens, extra double quotes
I don't think you want word query as the translation for "="; word query just says that word appears somewhere in the field in question; I would think that would be a value query instead.
You might want to take a look at cts:parse which takes a string with ANDs and ORs etc. plus bindings for fields and parses a query string into a cts:query
That said, if you assume the AND mixed in with the ORs binds to the closest clause, i.e. as parenthesized so:
(collection = "TRBA" AND
fulltext = 1 AND
(dnta = "Briefing" OR
dnta = "Conference" OR
snta = "Workshop" OR
(snta = "Published in" AND (snta = "this article" OR dnta = "Journal"))
) AND
(cand IN ("Research","Development Center") OR
scn IN ("424778","98814","393825"))
then I would translate this something like this:
cts:and-query((
cts:collection-query("/dbs/TRBA"),
cts:element-value-query(xs:QName("meta:FullTextExists"),"1"),
cts:or-query((
cts:field-value-query("dnta",("Briefing","Conference")),
cts:field-value-query("snta","Workshop"),
cts:and-query((
cts:field-value-query("snta","Published in"),
cts:or-query((
cts:field-value-query("snta","this article"),
cts:field-value-query("dnta","Journal")
))
))
)),
cts:or-query((
cts:field-value-query("cand",("Research","Development Center")),
cts:field-value-query("scn",("424778","98814","392825"))
))
))
It is a pretty direct mapping.
You simply have several typos in your code. There's an extra double quote in the collection-query and you're missing a comma between items in the last or-query.
Once fixing those the code will run. But a pro tip: don't ever fetch URIs only to fetch documents. You're wasting effort. Just fetch the documents directly with a search passing the query.
let $q := cts:and-query((...))
return cts:search(doc(), $q)[1 to 10]
You probably want to add a limit like [1 to 10] as well unless you really intend to return the full result set.
I have a linq statement that returns a list of records based on where clause
This where clause checks for two parameter values.
Out of which one parameter is optional.
so i need a suggestions if i can switch my where clause based on the optional Parameter
something like this
if(locid==0)
{
where (p.CustomerID == custid)
}
else{
where (p.CustomerID == custid) & (p.LocationID == locid )
}
can any one help me how can i get this work.
thanks
You could try writing it like this:
where (p.CustomerID == custid) && (locid == 0 || p.LocationID == locid )
Yes - queries can be composed (although you don't need this for this particular case as #rsbarro pointed out):
var query = p;
if(locid==0)
query = query.Where( p =>p.CustomerID == custid);
else
query = query.Where( p =>p.CustomerID == custid & p.LocationID == locid);
//any other conditions
As BrokenGlass mentioned, you should use composition:
IQueryable<Foo> query = unfiltered.Where(p => p.CustomerID == custId);
if (locid != 0)
{
query = query.Where(p => p.LocationID == locid);
}
Note that the query is not executed until you start reading data from it, so you needn't worry about this making multiple requests.
It looks like in your original post you were trying to use query syntax piecemeal - that won't work, but the "dot notation" is pretty simple here. You can always create your initial query using a query expression if you want - again, that query won't be executed immediately anyway.
I have a query that prints userid in label1 when username is entered.Works fine; but i want to write query for username and password that prints userid. so how can i write it? i tried writing using 'and' operator but dont seems to work.
int id = (from auser in lq.logins
where auser.username == userNameString //&& auser.Password =pwdString
select auser.userid).SingleOrDefault();
label1.Text = id.ToString();
Thanks
Ani
It looks like you used the assignment operator = instead of the comparison operator ==. The query should be:
int id = (from auser in lq.logins
where auser.username == userNameString && auser.Password == pwdString
select auser.userid).SingleOrDefault();
label1.Text = id.ToString();
It probably doesn't work becase you used = instead of ==.
Assuming that we have the following table:
Person:
PersonID,
Name,
Age,
Gender
And we are providing a search function that allows users to search the table according to the name and/or the age.
The tricky part in writing the SQL ( or LINQ) query is that the users can choose to search for both field, or any one field, or no field. If he wants to search for all then he would just have to leave the textbox blank.
The logic to do this can be written as follows:
var p;
if(Name_TextBox=='')
{
p=from row in person
select row ;
}
else
{
p= from row in person
where row.Name=Name_TextBox
select row ;
}
// repeat the same for age
Now after a while the code gets very long and messy... How can I compress the above into a single query with no if-else?
Try code like this
string personName = txtPersonName.Text;
int personAge = Convert.ToInt32(txtAge.Text);
var opportunites = from p in this.DataContext.Persons
select new
{
p.PersonID,
p.Name,
p.Age,
p.Gender
};
if (personsID != 0)
opportunites = opportunites.Where(p => p.PersonID == personID);
if (personName != string.Empty)
opportunites = opportunites.Where(p => p.Name.StartsWith(personName));
if (personAge != 0)
opportunites = opportunites.Where(p => p.Age == personAge);
This will work fine. If personName is not given it will be not add to where, and if given then it will added.
One alternative which I have used in SQL which could be implemented in Linq too is
var p = from p in Person
where p.Name == Name_TextBox || Name_TextBox == String.Empty
select p;
(Note that your 'linq' is using SQL syntax, which won't compile. Also you can't declare a var as you are doing without directly assigning a value)
why not use the null coalescing operator? eg.
var products = from a in context.products
where a.ID == (productID ?? a.ID)
select a;
This works really well on my system