I try Get 5 Object in each group to display.
I tried code like this:
var BBS = (from bb in db.Object
where SubjectList.Contain(bb.Type)
select new ObjectModel {
Subject = bb.Subject,
CDate = bb.CDate
}).GroupBy(a => a.BBSTypeSubject).Take(5);
but it doesn't work.
and then I try it by using Foreach
First off, realize that C# is case sensitive, so you need to spell function names like Take and Contains correctly. But you can solve this problem fairly easily by just using this overload of GroupBy instead.
var BBS = (from bb in db.Object
where SubjectList.Contains(bb.Type)
select new ObjectModel {
Subject = bb.Subject,
CDate = bb.CDate
}).GroupBy(a => a.BBSTypeSubject, (k, g) => g.Take(5));
The second parameter allows you to specify what result object will be returned for each group. In this case, I simply take the first 5 items from the group and return those instead.
When you select new ObjectModel, there's no property called BBSTypeSubject. You need to include that. So it should be
select new ObjectModel {
Subject = bb.Subject,
CDate = bb.CDate,
BBSTypeSubject= ???
}
Related
I am kind of new to Lambda Expressions, I have tried to work out a simple solution to the following task I have set myself.
A customer has a collection of cars. Use LINQ to get a total number of cars he has.
Code below, not sure if this is correct? My second question is how do you display the TotalNumberCars to a textbox?
using (Entities dbcontext = new Entities())
{
var ListByOwner = from c in dbcontext.Owners
where c.OwnerID == OwnerID
group c by c.Cars into g
select new
{
Owner = g.Key,
TotalNumberCars = g.Sum(x => x.Cars)
};
lblTotalCars.Text = ListByOwner.ToList();
}
I don't know how your entity data model is structured, but I would do it like this:
using (var dbContext = new Entities())
{
var numberOfCars = dbContext.Cars.Count(c => c.OwnerId == OwnderId);
lblTotalCars.Text = numberOfCars.ToString();
}
If there's no c.OwnerId then maybe you can access it by typing c.Owner.OwnerId.
ListByOwner.ToList() is an array (generic list) of your new items from your Select projection. Each item is a dynamic entity with two properties of Owner and TotalNumberCars. You need to index or foreach into the list, extract what is needed into a string and that can be your text.
Such as lblTotalCars.Text = ListByOwner[0].Owner; will display the first item's owner.
Take this and fill in what you need.
check this code
lblTotalCars.Text = ListByOwner.ToList().sum(c=>c.TotalNumberCars).ToString();
I'm new in LinqPad. I already solved all my problems except the following:
How can I get the .Count() of one column, respectively the list in the one cell. Like you see in the picture.
My code example is:
var test2 = (from d in DocumentTypeLabels
select new {d.DocumentTypePIMID, d.Name, d.DocumentType.Documents}
)
.Take(1); test2.Dump();
My idea was:
var test2 = (from d in DocumentTypeLabels
select new {d.DocumentTypePIMID, d.Name, (d.DocumentType.Documents).Count()}
)
.Take(1); test2.Dump();
but unfortunately this doesn't work.
Does anyone have an idea?
Given the type of DocumentType.Documents is a Collection, you could try using the Length or Count properties from you collection and name a property on your result. For sample:
var test2 = (from d in DocumentTypeLabels
select new {
d.DocumentTypePIMID,
d.Name,
DocumentsTotal = d.DocumentType.Documents.Count()
}).Take(1);
When you do not define a name for a property on the select statement, it will generate a property with a name of the property you have provided. For sample: x.Name will be Name on result.
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've got one question here. I'm a newbie so pardon with my terminologies, I am querying a data table wherein I need to group this data table according to date and their unique access code.
var tMainTable = (from System.Data.DataRow b in _tData.data_table.Rows
group b by b["ACCESS_CODE"] into bGroup
select new
{ bGroup });
in my current grouping above, I am grouping my data table according to access code. My data table is composed of 3 fields: DATE, ACCESS_CODE, COUNT. This is provided that I cant make my datatable AsEnumerable() type.
So this time, I want to add in its condition, which is grouping by date as well... is there such thing as:
var tMainTable = (from System.Data.DataRow b in _tData.data_table.Rows
**group b by b["ACCESS_CODE"] AND b["DATE"] into bGroup**
select new
{ bGroup });
Thanks for any inputs.
Use an anonymous type for your grouping:
var codeDateGroups = _tData.data_table.AsEnumerable()
.GroupBy(r => new {
AccessCode = r.Field<string>("ACCESS_CODE"),
Date = r.Field<DateTime>("DATE")
});
You can access it via the Key:
foreach(var group in codeDateGroups)
Console.WriteLine("Code=[{0}] Date=[{1}]"
, group.Key.AccessCode
, group.Key.Date);
var tMainTable = (from System.Data.DataRow b in _tData.data_table.Rows
group b by new { AccessCode = b["ACCESS_CODE"], Date = b["DATE"] } into bGroup
select new
{ bGroup });
var groups = _tData.data_table.AsEnumerable()
.GroupBy(row=> new {row["ACCESS_CODE"],row["DATE"] });
When you query existing linq results, it's like they're stuck a layer deeper than the original result. Let me explain what I mean by this.
In the example below, after getting ResultSorted, to get to the data therein, you have to use RowSorted.All.TableData.Field, but in the unsorted Result, you could just do Row.TableData.Field. In the sorted data, you have to use .All to get to the rest of the data, which is like an extra layer to get to the data you're looking for.
How can I get it so I can query Result without getting this extra layer? Thanks Stack-O!
var Result =
from a in Db.Table
select new {TableData = a};
var ResultSorted =
from a in Result
orderby a.TableData.Field
select new {All = a};
foreach(var RowSorted in ResultSorted)
{
MessageBox.Show(RowSorted.All.TableData.ToString());
}
You can use
var Result =
from a in Db.Table
select a;
var ResultSorted =
from a in Result
orderby a.Field
select a;
foreach(var RowSorted in ResultSorted)
{
MessageBox.Show(RowSorted.ToString());
}
Edit:
The thing is that
select new {TableData = a};
creates a new anonymous type with a field called TableData, like this
class Tmp1
{
TableType TableData {get; set;}
}
and
select new {All = a};
creates a new anonymous type with a field called TableData, like this
class Tmp2
{
Tmp1 All {get; set;}
}
Edit 2:
If you select a directly you don't create the extra anonymous type, instead you return the TableType.
You are returning a new instance of an anonymous type in each of your LINQ queries:
select new {TableData = a};
select new {All = a};
What you are saying to the compiler is (in the first LINQ query), "Give me a new instance of an anoymous type. I want this anonymous type to have one property named TableData and I want the value for that property to be a."
If you simply return a instead of an anoymous type, you shouldn't need to go through the properties of the nested types to get the data. Try this:
var Result =
from a in Db.Table
select a;
var ResultSorted =
from a in Result
orderby a.TableData.Field
select a;
foreach(var RowSorted in ResultSorted)
{
MessageBox.Show(RowSorted.ToString());
}
var ResultSorted =
from a in Db.Table
orderby a.Field
select a.ToString();
Edit: Fixed, didn't see the first query. This should be identical now. There is no need to create anonymous objects all the time.