I tried to use the suggestion provided here for using In operator in linq but, i am not able to convert my requirement into LINQ statement.
Below is the SQL query which i need to convert to Linq
select *
from navigator_user_field_property
where user_id = 'albert'
and field_id in (
select field_id
from navigator_entity_field_master
where entity_id = 1
and use_type = 0)
order by field_id
I want this to be converted to a Efficient Linq.
Most of the answers deal with the predetermined list of string array which is not working in my case.
Thanks
Looks like a join to me:
var query = from navigator in db.NavigatorUserFieldProperties
where navigator.UserId == "albert"
join field in db.NavigatorEntityFieldMasters
.Where(f => f.EntityId == 1 && f.UseType == 0)
on navigator.FieldId equals field.FieldId
select navigator;
Note that this will return the same value multiple times if there are multiple fields with the same ID - but I suspect that's not the case.
You could do a more literal translation like this:
var query = from navigator in db.NavigatorUserFieldProperties
where navigator.UserId == "albert" &&
db.NavigatorEntityFieldMasters
.Where(f => f.EntityId == 1 && f.UseType == 0)
.select(f => f.FieldId)
.Contains(navigator.FieldId)
select navigator;
... and that may end up translating to the same SQL... but I'd personally go with the join.
Here is an efficient and readable LINQ query:
var fields =
from field in db.navigator_entity_field_masters
where field.entity_id == 1 && field.user_type == 0
select field;
var properties =
from property in db.navigator_user_field_properties
where property.user_id == "albert"
where fields.Contains(property.field)
select property;
Look mama!! Without joins ;-)
Related
For the following query:
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
{
ModifiedAmounts = SchExpGroup.Select(a => a.ModifiedAmounts),
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
};
I want to filter the above query on a condition so that result gives only those records where "ModifiedAmounts" are not null. I have tried as follow:
if (rbList2.SelectedIndex == 6)
{
result = result.Where(a => a.ModifiedAmounts != null));
}
but this gives error as:
Cannot compare elements of type
'System.Collections.Generic.IEnumerable`1'. Only primitive types,
enumeration types and entity types are supported.
Any suggestions as I am lost as how to rephrase the filtered query.
I think the problem is that ModifiedAmounts will never be null. Select will return an empty list. Unless SchExpGroup is null in which case you will get a null reference exception.
Try changing your code to
result = result.Where(a => a.ModifiedAmounts.Any());
if (rbList2.SelectedIndex == 6)
{
result = result.Where(a => a.!ModifiedAmounts.Any());
}
I got this linq query which searches for selected values in my database using dropdowns.
Is there a way to hide the "join" in the linq query if the ddlCategory is null? I want this because the result of the search shows duplicated-rows because my documents can have many Categories.?? hope you understand what i mean.. Can anyone help??
var documents = from d in data.tblDocuments
join sc in data.tblSubCategories on d.DocId equals sc.DocId
orderby d.Docyear descending
where
(string.IsNullOrEmpty(person) || d.DocPerson.Equals(person)) &&
(string.IsNullOrEmpty(year) || d.Docyear.Equals(year)) &&
(string.IsNullOrEmpty(law) || d.DocLaw.Equals(law)) &&
(string.IsNullOrEmpty(court) || d.DocCourt.Equals(court)) &&
(string.IsNullOrEmpty(category) || sc.CategoryId.Equals(category)) &&
(string.IsNullOrEmpty(casenr) || d.DocNr.Equals(casenr))
select d;
Use lambda syntax:
var query = data.tblDocuments;
if (condition) // conditionally add join
query = query.Join(data.tblSubCategories.Where(sc => sc.CategoryId == category),
d => d.DocId, sc => sc.DocId, (d,sc) => d);
// continue to compose query
query = query.OrderByDescending(d => d.Docyear)
.Where(d => ...);
BTW you can compose filtering based on conditions:
if (!String.IsNullOrEmpty(person))
query = query.Where(d => d.DocPerson == person);
I want to do a LINQ NOT EXISTS on query MULTIPLE TABLES.
All examples on Google or SO are handling two tables I'm working with three so I'm struggling as a newbie on LINQ on how to reference them correctly.
First I tried this LINQ query
var nocertificates = (
from x in rmdb.t_certificates
from ce in rmdb.t_user_certificates
from u in rmdb.t_users
where u.id == ce.uid && ce.value != x.id
select x).AsEnumerable().Select(x => new ViewModelCheckBox()
{
Value = x.id.ToString(),
Name = x.name,
Checked = false
});
I used the ugly three times from as I'm not that good with creating types for joining.
But that gave wrong result and I realized I had to go for a NOT EXISTS
So I built a new query in T-SQL
This is the SQL query it works!
select distinct * from t_certificates tc
where NOT EXISTS
(
select distinct * from t_users tu, t_user_certificates tuc
WHERE tu.email = 'user#email.com'
and tu.id = tuc.[uid]
and tuc.value = tc.id
)
How would I do that in LINQ?
This is the question, I will award my answer for that!
BUT!
When we are at it... I'm really curious on the answer.. Is it possible to do one LINQ query that return an Ienumerable with both those that EXISTS and NOT EXISTS resulting in an object which will hold DIFFERENT VALUES on the checked property EXISTS -> CHECKED = true NOT EXISTS -> CHECKED = false
This is how I create my object.
.Select(x => new ViewModelCheckBox()
{
Value = x.id.ToString(),
Name = x.name,
Checked = this should be different based on exists or not
});
The LINQ answer should look something like this (untested):
var nocertificates =
from x in rmdb.t_certificates
join tuc in (
from u in rmdb.t_users
join ce in rmdb.t_user_certificates on u.id == ce.uid
select ce.value
) on tuc.value = tc.id into tuc
from y in tuc.DefaultIfEmpty()
where y == null
select x;
This is what I ended up using!
var query = (from tc in rmdb.t_certificates
where !(
from tu in rmdb.t_users
from tuc in rmdb.t_user_certificates
where tu.email == username
&& tu.id == tuc.uid
&& tuc.value == tc.id select tc).AsEnumerable().Any()
select new ViewModelCheckBox()
{ Checked = false,
intconverter = tc.id,
Name = tc.name
});
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.
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