I would like to replace "var" with the actual type definition. I believe it returns an IEnumerable<>, but I can't figure out what to put for T? I tried debugging with GetType(), but still don't get it...
var LinqResults = from row in dt.AsEnumerable()
orderby row.Field<string>("Category"), row.Field<int>("WorkOrderVersion")
group row by new { Category = row.Field<string>("Category"), WorkOrderVersion = row.Field<int>("WorkOrderVersion") } into grp
select new
{
Category = grp.Key.Category,
WorkOrderVersion = grp.Key.WorkOrderVersion,
};
You can't combine a use of an anonymous type with a specific type because anonymous types provide no name for you to put in for a T inside IEnumerable<T>. In fact, use of anonymous types is an important use case for adding var to the C# language in the first place.
You can define a named type for the result, lie this:
class VersionedWorkOrder {
public string Category { get; set; }
public int WorkOrderVersion { get; set; }
}
IEnumerable<VersionedWorkOrder> linqResults = from row in dt.AsEnumerable()
orderby row.Field<string>("Category"), row.Field<int>("WorkOrderVersion")
group row by new { Category = row.Field<string>("Category"), WorkOrderVersion = row.Field<int>("WorkOrderVersion") } into grp
select new VersionedWorkOrder {
Category = grp.Key.Category,
WorkOrderVersion = grp.Key.WorkOrderVersion
};
Related
I'm looking for some help with a LINQ query to filter on a property/enum of a custom object which is in a nested List, and want to maintain the parent object in return list.
For example/clarity/sample code, I have a parent object, which has in it a List based on class and enum below:
public class Stage {
public String Name { get; set;}
public List<Evaluation> MyEvaluations { get; set;}
}
public class Evaluation {
public float Result { get; set; }
public enumResultType ResultType { get; set; }
}
public enum enumResultType {
A,B,C
}
One can simulate sample data along those lines with something like:
List<Stage> ParentList = new List<Stage>();
Stage Stage1 = new Stage() { Name = "Stage1",
MyEvaluations = new List<Evaluation>() {
new Evaluation() { ResultType = enumResultType.A, Result=5 },
new Evaluation() { ResultType = enumResultType.B, Result=10},
new Evaluation() { ResultType = enumResultType.B, Result=11},
new Evaluation() { ResultType = enumResultType.C, Result=5}
}};
Stage Stage2 = new Stage() { Name = "Stage2",
MyEvaluations = new List<Evaluation>() {
new Evaluation() { ResultType = enumResultType.A, Result=10},
new Evaluation() { ResultType = enumResultType.B, Result=20},
new Evaluation() { ResultType = enumResultType.C, Result=20}}};
ParentList.Add(Stage1);
ParentList.Add(Stage2);
What I want to be able to do, via LINQ, is to select from the Parentlist object, all the items with only a filtered list where the ResultType in the Evaluations List matches a proper condition...
I don't want to repeat the parent object multiple times (seen selectmany), but rather a filtered down list of the MyEvaluations where the ResultType matches, and if this list has items (it would) return it with the parent.
I've played with:
ParentList.Select(x => x.MyEvaluations.FindAll(y => y.ResultType==enumResultType.B)).ToList();
however this returns only the inner list... whereas
ParentList.Where(x => x.MyEvaluations.Any(y => y.ResultType==enumResultType.B)).ToList();
returns ANY.. however I am missing how to get the list of MyEvaluations to be filtered down..
In my Example/sample data, I would like to query ParentList for all situations where ResultType = enumResultType.B;
So I would expect to get back a list of the same type, but without "Evaluation" which are equal to ResultType.A or .C
Based on dummy data, I would expect to be getting something which would have:
returnList.Count() - 2 items (Stage1 / Stage2) and within that Stage1 --> foreach (item.Result : 10, 11 Stage2 --> foreach (item.Result : 20
Can this be done without going to projections in new anonymous types as I would like to keep the list nice and clean as used later on in DataBinding and I iterate over many ResultTypes?
Feel like I'm missing something fairly simple, but fairly new to LINQ and lambda expressions.
Did you try these approaches already? Or is this not what you're looking for ?
//creating a new list
var answer = (from p in ParentList
select new Stage(){
Name = p.Name,
MyEvaluations = p.MyEvaluations.Where(e => e.ResultType == enumResultType.B).ToList()
}).ToList();
//in place replacement
ParentList.ForEach(p => p.MyEvaluations = p.MyEvaluations.Where(e => e.ResultType == enumResultType.B).ToList());
As you can see, I got this error when I built Data Gird using Kendo UI. Does anybody could point out where I'm wrong in my code below.
private IEnumerable<Product> GetSubProduct()
{
var context = new AdvenDBEntities();
var subcate = context.Products.Select(p => new Product
{
ProductID = p.ProductID,
Name = p.Name,
Color = p.Color,
ListPrice = p.ListPrice,
}).ToList();
return subcate;
}
Error:
The entity or complex type 'AdventureWorks2012Model.Product' cannot be constructed in a LINQ to Entities query.
Thank you so much for your time!
Since Product is an entity of model, you are creating new object of this entity while selecting the records, which is NOT good idea, I am NOT sure how model will handle this kind of behaviour that is why it is preventing you to do so, (I guess). Anyway you can change the code to this,
private IEnumerable<Product> GetSubProduct()
{
var context = new AdvenDBEntities();
var subcate = context.Products.ToList();
return subcate;
}
BTW your function name indicating that you are missing a Where clause.
Also you can create some custom DTO class and use it instead.
E.g.
class ProductDTO
{
public int ProductID { get; set; }
public string Name { get; set; }
public string Color { get; set; }
public decimal ListPrice { get; set; }
}
private IEnumerable<ProductDTO> GetSubProduct()
{
var context = new AdvenDBEntities();
var subcate = context.Products.Select(p => new ProductDTO
{
ProductID = p.ProductID,
Name = p.Name,
Color = p.Color,
ListPrice = p.ListPrice,
}).ToList();
return subcate;
}
The first bad smell code I can point out for you. DBContext implements IDisposable so you are responsible for calling Dispose on it. In all, but one case in here, using block
You must build query to get all the product and then extract from it.
private IEnumerable<Product> GetSubProduct()
{
using (var context = new AdvenDBEntities())
{
// Get all constructed type product and then select from it
var subcate = context.Products
.ToList()
.Select(p => new Product
{
ProductID = p.ProductID,
Name = p.Name,
Color = p.Color,
ListPrice = p.ListPrice,
});
return subcate;
}
}
I have a method that selects two fields from database where text in first field match some value
public static List<List<string>> SelectForSearch(string letter)
{
var data = (from p in model.City
where p.Name.StartsWith(letter)
select new List<string> { p.Name, p.CountryName }).ToList();
return data;
}
But it returns me a list like this:
[0][0]Australia
[0][1]Ballina
[1][0]Berry
[1][1]Australia
[2][0]Australia
[2][1]Bendigo
...
Country and City possition don't have a static index like this:
[0][0]Ballina
[0][1]Australia
[1][0]Berry
[1][1]Australia
[2][0]Bendigo
[2][1]Australia
...
Your issue is that in your select statement, instead of creating a type with Name and CountryName you are creating a List of strings. The List initialiser allows you to pass in the values when the list is constructed by placing them in { } and you are using this ability by accident, as you saw it creates a list of strings where the name is the first element and the country name is the second element. What you want to be doing is more like:
var data = (from p in model.City
where p.Name.StartsWith(letter)
select new { City = p.Name, CountryName = p.CountryName }).ToList();
return data;
This is using anonymous types which is not good as you want to declare a type for the return value. So you should really create a class for storage, for example:
public class CityCountryPair
{
public String City { get; set; }
public String CountryName { get; set; }
}
then your method becomes
public static List<CityCountryPair> SelectForSearch(string letter)
{
var data = (from p in model.City
where p.Name.StartsWith(letter)
select new CityCountryPair() { City = p.Name,
CountryName = p.CountryName
}).ToList();
return data;
}
I have been using the DynamicQueryable Linq extensions featured in Scott Guthrie's blog post.
The documentation has a table of supported operators. One of the primary operators is the following:
x[…]
Array or indexer access. Multi-dimensional arrays are not supported.
However, I cannot figure out how it can be used.
I didn't expect any of the following to work and in fact they don't.
var ctx = new MyDbContext();
var parameters = new Object[] { new int[] { 1, 2, 3 } };
var qry = ctx.Set<User>().Where<User>("it.Id in #0", parameters);
var qry = ctx.Set<User>().Where<User>("it.Id.In(#0)", parameters);
var qry = ctx.Set<User>().Where<User>("it.Id = #0", parameters);
var qry = ctx.Set<User>().Where<User>("#0.Contains(it.Id)", parameters);
It is basically an In query, but I am not sure how to express it.
This is perhaps a misunderstanding. Meant is that it is possible to query for collection elements at a specific index position. For example:
public class Order
{
public List<OrderDetail> OrderDetails { get; set; }
}
public class OrderDetail
{
public string Description { get; set; }
}
Then you can query for all orders which have the Detail description "Bicycle" in the third OrderDetail by:
string parameter = "Bicycle";
var qry = ctx.Set<Order>().Where<Order>("it.OrderDetails[2].Description == #0",
parameter);
I think for your purpose you need to build up an "OR" chain "it.Id == 1 or it.Id == 2 or it.Id == 3" (or build this query string dynamically in a loop) without parameters in the Where method.
I want to group by the categoryid and then do a count on this. But I don't know how to do this. I have tried a couple of ways without success. Here is my latest:
public class Count
{
public int TradersCount { get; set; }
public int Id { get; set; }
public string Description { get; set; }
}
public IQueryable<Count> CountTradersAttachedToCategories()
{
var data = from tc in _db.tblTradersCategories
select new Count
{
Description = tc.tblCategory.description,
Id = tc.tblCategory.categoryId,
TradersCount = tc.Select(x => x.categoryid).GroupBy().Count()
};
return data;
}
tblTradersCategories joins both
tblTraders/tblCategories
A single trader can have many categories
A single category can have many traders
Thanks in advance for any help.
Clare
Try this:
var data = from tc in _db.tblTradersCategories
group tc by new { tc.tblCategory.categoryId,
tc.tblCategory.description } into g
select new { Count = g.Count(),
Id = g.Key.categoryId,
Description = g.Key.description };
If you want that in your Count class you may need to use AsEnumerable() to perform the conversion in process:
var converted = data.AsEnumerable()
.Select(c => new Count { TradersCount = c.Count,
Id = c.Id,
Description = c.Description });
You can try doing them all in one go:
var data = from tc in _db.tblTradersCategories
group tc by new { tc.tblCategory.categoryId,
tc.tblCategory.description } into g
select new Count { TradersCount = g.Count,()
Id = g.Key.categoryId,
Description = g.Key.description };
But I don't know if that will work. It depends on how the LINQ provider handles it.