I need to retrieve a list of entities from my database that matches a list of items in a plain list (not EF). Is this possible with Entity Framework 4.1?
Example:
var list = new List<string> { "abc", "def", "ghi" };
var items = from i in context.Items
where list.Contains(i.Name)
select i;
This works great to return rows that match one property, but I actually have a more complex property:
var list = new List<Tuple<string, string>>
{
new Tuple<string,string>("abc", "123"),
new Tuple<string,string>("def", "456")
};
// i need to write a query something like this:
var items = from i in context.Items
where list.Contains(new Tuple<string,string>(i.Name, i.Type))
select i;
I know that is not valid because it will say it needs to be a primitive type, but is there any way to do what I'm trying to accomplish or will I need to resort to a stored procedure?
You have a few options:
1) You could, of course, write a stored procedure to do what you need and call it.
2) You could read the table into memory and then query the in memory list...that way you don't have to use primitives:
var items = from i in context.Items.ToList()
where list.Contains(new Tuple<string, string>(i.Name, i.Type))
select i;
3) You could also convert your query to use primitives to achieve the same goal:
var items = from i in context.Items
join l in list
on new { i.Name, i.Type } equals
new { Name = l.Item1, Type = l.Item2 }
select i;
I would go with the second option as long as the table isn't extremely large. Otherwise, go with the first.
You need to break it down to sub-properties. For example, something like (this might not compile, i'm not able to test at the moment, but it should give you something to work with):
var items = from i in context.Items
where list.Select(x => x.Item1).Contains(i.Name)
&& list.Select(x => x.Item2).Contains(i.Type)
select i;
You have to think about what the resulting SQL would look like, this would be difficult to do directly in SQL.
My suggestion would be you split out one field of the tuples and use this to cut down the results list, get back the query result then filter again to match one of the tuples e.g.
var list = new List<string> { "abc", "def" };
var list2 = new List<Tuple<string, string>>
{
new Tuple<string,string>("abc", "123"),
new Tuple<string,string>("def", "456")
};
var items = (from i in context.Items
where list.Contains(i.Name)
select i)
.AsEnumerable()
.Where(i => list2.Any(j => j.val1 == i.Name && j.val2 == i.Type);
Related
I'm trying to convert a SQL expression to Linq but I can't make it work, does anyone help?
SELECT
COUNT(descricaoFamiliaNovo) as quantidades
FROM VeiculoComSeminovo
group by descricaoFamiliaNovo
I try this:
ViewBag.familiasCount = db.VeiculoComSeminovo.GroupBy(a => a.descricaoFamiliaNovo).Count();
I need to know how many times each value repeats, but this way it shows me how many distinct values there are in the column.
You can try:
var list = from a in db.VeiculoComSeminovo
group a by a.descricaoFamiliaNovo into g
select new ViewBag{
familiasCount=g.Count()
};
or
var list = db.VeiculoComSeminovo.GroupBy(a => a.descricaoFamiliaNovo)
.Select (g => new ViewBag
{
familiasCount=g.Count()
});
If you need column value:
new ViewBag{
FieldName=g.Key,
familiasCount=g.Count()
};
You don't need the GROUP BY unless there are fields other than the one in COUNT. Try
SELECT
COUNT(descricaoFamiliaNovo) as quantidades
FROM VeiculoComSeminovo
UPDATE, from your comment:
SELECT
COUNT(descricaoFamiliaNovo) as quantidades,
descricaoFamiliaNovo
FROM VeiculoComSeminovo
GROUP BY descricaoFamiliaNovo
That's it as SQL. In LINQ it is something like:
var reponse = db.VeiculoComSeminovo.GroupBy(a => a.descricaoFamiliaNovo)
.Select ( n => new
{Name = n.key,
Count = n.Count()
}
)
Not tested.
Ty all for the help.
I solved the problem using this lines:
// get the objects on db
var list = db.VeiculoComSeminovo.ToList();
// lists to recive data
List<int> totaisFamilia = new List<int>();
List<int> totaisFamiliaComSN = new List<int>();
// loop to cycle through objects and add the values I need to their lists
foreach (var item in ViewBag.familias)
{
totaisFamilia.Add(list.Count(a => a.descricaoFamiliaNovo == item && a.valorSeminovo == null));
totaisFamiliaComSN.Add(list.Count(a => a.descricaoFamiliaNovo == item && a.valorSeminovo != null));
}
The query was a little slow than I expected, but I got the data
How would you write "SELECT col.a, col.b FROM TABLE WHERE ID = 1" in LINQ to Entity 6 so that you could save col.a into variable A and col.b into variable B. You can do this with SqlReader by retrieving the index or column name, but with LINQ to Entity it is returned as one object. When returning a two field LINQ query to a list, both field are saved to the first index of the list and can only be accessed as the same list element. Is it standard to create two LINQ queries, one for each variable? Or am I missing part of the process?
Current query:
var result = (from col in cxt.Table
where col.ID == "1"
select new {col.a, col.b}).ToList();
If you are expecting exactly one record to return from database then what you can do:
var result = cxt.Table.FirstOrDefault(x => x.ID == "1");
//Notice that might be null if has not result
var a = result.a;
var b = result.b;
Will look very similar in query syntax but I think this method syntax neater in this case
I am not sure what exactly you are looking for. But selecting two variable by Linq is not so hard.
var value = (from ta in db.YourTable
where ta.ID = id
select new {
A = ta.a,
B = ta.b
}).FirstOrDefault();
var a = value.A;
var b = value.B;
If you use ToList() instead of FirstOrDefault(), you will get a list contain zero or more objects. You can simply use a loop to get field from each object.
forach(var value in values)
{
var a = value.A;
var b = value.B;
}
I have a list of string
List<string> list = new List<string>();
list.Add("john");
list.Add("David");
list.Add("Sam");
Now I want to check whether my column in database contains these list Items.
var v = db.employee.where(s => s.Content.Contains(list));
My question is how can I match all list items to database column in just one query without using any loop. The query must return result if single list item is matched with column. The query I mentioned above not working. Please help me to solve this.
This will only work with the assumption that your db is an Entity Framework DbContext and that s.Content is a string. If you're using some other ORM then it may not work.
List<string> list = new List<string>();
list.Add("john");
list.Add("David");
list.Add("Sam");
var v = db.employee.Where(s => list.Contains(s.Content)).ToList();
You can do this:
List<string> list = new List<string>();
list.Add("john");
list.Add("David");
list.Add("Sam");
var v = db.employee
.ToList()
// This filtering doesn't happen in your SQL server.
.Where(s => list.Any(x => s.Content.Contains(x)));
You can try to omit .ToList() line but I'm afraid your ORM will not know how to convert the query to SQL.
If you want the whole query to be executed in SQL you should consider building the query this way:
var query = db.employee.AsQueryable();
query = list.Aggregate(query,
(query, name) => query.Where(empl => empl.Content.Contains(name)));
what about:
List<string> list = new List<string> {"john", "Warwick", "Sam"};
var vresult = _db.employee.Where(x => list.Contains(x.Content)).ToList();
please indicate what you are expecting...? like how is it not working?
If return is different than null, exists.
public List<Employee> CheckIfExists(List<string> nameList)
{
if (nameList == null)
{
return null;
}
string inClause = "";
foreach (var item in nameList)
{
inClause = string.Format("{0},{1}", inClause, item);
}
return db.employee.SqlQuery("SELECT * FROM employee WHERE employee.Name IN (#p0)", inClause).ToList();
}
Each element of list will be passed as an argument to s.Content.Contains
and here s is an employee record.
var v = db.employee.Where(s => list.Any(s.Content.Contains));
This might help you,
list with name= {"john", "David", "Sam"}
you want to check if John/David/Sam exists in the employee table.
The below query is to check if the particular name exists in employee or not
var _data = _db.employee.Where(emp => list.Any(li => li.name == emp.name)).ToList();
LINQ in query syntax:
var result = from o in db.employee
where list.Contains(o.Content)
select o;
I've got a table Installation which can contains one or many Equipements.
And for functionnal reasons, I've overwritten my table Installation and added a field NbrEquipements.
I want to fill this field with Linq, but I'm stuck...
Due to special reasons, there is no relation between these to tables. So, no Installation.Equipements member into my class. Therefore, no Installation.Equipements.Count...
I'm trying some stuff. Here is my code:
var query = RepoInstallation.AsQueryable();
// Some filter
query = query.Where(i => i.City.RegionId == pRegionId));
int?[] etatIds = { 2, 3 };
query = (from i in query
select new Installation
{
NbrEquipements= (from e in RepoEquipement.AsQueryable()
where e.InstallationSpecialId == i.SpecialId
&& (etatIds.Contains(e.EquEtat))
select e.SasId
).Count()
});
But with this try, I got this error:
The entity or complex type 'myModel.Installation' cannot be constructed in a LINQ to Entities query
I've tried some other stuff but I'm always turning around...
Another thing that can be useful for me: It would be great to fill a field called Equipements which is a List<Equipement>.
After that, I would be able to Count this list...
Is it possible ?
Tell me if I'm not clear.
Thanks in advance.
Here is the final code:
//In the class:
[Dependency]
public MyEntities MyEntities { get; set; }
//My Methode code:
var query = MyEntities .SasInstallations.AsQueryable();
// Some filter
query = query.Where(i => i.City.RegionId == pRegionId));
var liste = new List<Installation>();
var queryWithListEquipements =
from i in query
select new
{
Ins = i,
EquipementsTemp = (from eq in MyEntities.Equipements.AsQueryable()
where eq.SpecialId == i.SpecialId
&& (etatIds.Contains(eq.SasEquEtat))
select eq
).ToList()
};
var listWithListEquipements = queryWithListEquipements.ToList();
foreach (var anonymousItem in listWithListEquipements)
{
var ins = anonymousItem.Ins;
ins.Equipements = anonymousItem.EquipementsTemp;
ins.NumberEquipements = ins.Equipements.Count();
liste.Add(ins);
}
return liste;
By the way, this is very very fast (even the listing of Equipements). So this is working exactly has I wished. Thanks again for your help everyone!
Use an anonymous type. EF does not like to instantiate entity classes inside a query.
var results = (from i in query
select new
{
NbrEquipements= (from e in RepoEquipement
where e.InstallationSpecialId == i.SpecialId
&& (etatIds.Contains(e.EquEtat))
select e.SasId
).Count()
})
.ToList();
Notice how I used select new instead of select new Installation.
You can then use the data inside the list (which is now in memory) to create instances of type Installation if you want like this:
var installations = results.Select(x =>
new Installation
{
NbrEquipements = x.NbrEquipements
}).ToList();
Here is how to obtain the list of equipment for each installation entity:
var results = (from i in query
select new
{
Installation = i,
Equipment = (from e in RepoEquipement
where e.InstallationSpecialId == i.SpecialId
&& (etatIds.Contains(e.EquEtat))
select e).ToList()
})
.ToList();
This will return a list of anonymous objects. Each object will contain a property called Installation and another property called Equipment (which is a list). You can easily convert this list (of anonymous objects) to another list of whatever type that you want.
I have little problem with my LINQ query (nHibernate)
I need to have count of objects znak with equal property Symbol
My query:
var tmp = (from znak in sesja.Query<Znak>()
group znak by znak.Symbol into r
select new { Name= r.Key.Name, SUM= r.Count() });
This query works, but I need to make object contains other properties of znak class.
In this case: select new { Name= r.Key.Name, SUM= r.Count() }); i can make new objects only from r.Key, (Symbol property). But I need other properties in my new object.
Is it possible ?
I recommend using lambda Linq syntax:
var items = sesja.Query<Znak().AsEnumerable();
var newList = items.GroupBy(x=>x.Symbol).Select(
x=> new { Name=x.Key.Name, Count = x.Count(), Items = x.ToList() });
read more about Linq syntax LINQ: Dot Notation vs Query Expression
I think that lambda syntax is more readable and looks much cleaner in code because it's more c# style not sql style.
Of course there will be no difference in IL code, always you can install tools like resharper, they can convert lambda syntax to sql-like syntax.
Try something like
var tmp = (from znak in sesja.Query<Znak>()
group znak by znak.Symbol into r
select new { Name= r.Key.Name, SUM= r.Count(), Items = r.ToList() });
Items property will contain actual objects in the group.