How does one use .ToList() Inside of a Linq Query? - linq

I've got a class that contains a list item. I would like for a linq query to populate the class, including this list. Here is my query:
var query = from c in context.Cars
select new CarListItem()
{
ID = c.ID,
Make = c.Make,
AvailableColors = context.CarColors.Where(u => u.CarID == c.ID).ToList()
};
Basically, I want to get a list of all of the cars, including a list of the available colors for each respective car.
The problem is that the inclusion of .ToList() within the query results in an error: An error occurred:
LINQ to Entities does not recognize the method 'System.Collections.Generic.List`1[CarSystem.Models.CarColors] ToList[CarColors](System.Collections.Generic.IEnumerable`1[CarSystem.Models.CarColors])' method, and this method cannot be translated into a store expression.
At this point, I don't know whether I am just using wrong syntax within the Linq query (should I use something other than .ToList()?) or if maybe the architecture of the models is wrong.

You can't. EF tries to translate ToList() to SQL and doesn't know how.
You could project to another type, then call ToList():
var query = (from c in context.Cars
select new
{
ID = c.ID,
Make = c.Make,
AvailableColors = context.CarColors.Where(u => u.CarID == c.ID)
}).ToList()
.Select(c => new CarListItem()
{
ID = c.ID,
Make = c.Make,
AvailableColors = c.AvailableColors.ToList()
});
or change the type of CarListItem.AvailableColors to IEnumerable<CarColor>:
var query = from c in context.Cars
select new CarListItem()
{
ID = c.ID,
Make = c.Make,
AvailableColors = context.CarColors.Where(u => u.CarID == c.ID)
};

Related

How to write LINQ query as one query?

I have the following query that groups locations and the average item cost and I would like to write it as one query but I cannot figure out the syntax. What LINQ do I need to do this? I have tried writing it different ways but the syntax is not correct.
var joinedData =
from r in shops
join i in items on r.shopId equals i.shopId
select new
{
Region = r.Location,
ItemCost = i.ItemCost
};
var AverageCostByLocation = joinedData
.GroupBy(m => new { m.Location})
.Select(m => new
{
Location= m.Key.Location,
AverageItemCost = m.Average(x => x.ItemCost)
});
Well, if you put first expression in parenthesis it should allow to join both expressions as they are. Also I'd probably get rid of second anonymous type for perfomance reasons (the new { m.Location} line is redundant, you might want to use .Key instead) :
var AverageCostByLocation =
(from r in shops
join i in items on r.shopId equals i.shopId
select new
{
Region = r.Location,
ItemCost = i.ItemCost
})
.GroupBy(m => m.Location)
.Select(m => new
{
Location= m.Key,
AverageItemCost = m.Average(x => x.ItemCost)
});

How to add/edit DataServiceQuery LINQ Projections in Silverlight?

Silverlight 5 / WCF Data Services 5.6.0 / Entity Framework 5 / Asynchronous LINQ DataServiceQuery
How can I reset/delete/uncache/remove the projections from my DataServiceQuery LINQ query in subsequent executions ?
Consider the below code:
var query =
(
from c in context.Customers
select new Customers()
{
ID = c.ID,
Name = c.Name,
}
) as DataServiceQuery<Customers>;
query.BeginExecute((result) =>
Dispatcher.BeginInvoke(() =>
{
// process results from query...
// query.EndExecute(result).ToList();
}), null);
In the above snippet, I'm creating a LINQ query with two projections (columns) which will return the ID and Name fields via WCF Data Services. This works fine; issue starts below...
In another method which executes later, I have a similar query to fetch additional columns/projections. However, the below LINQ query returns the same resultset as above and ignores the additional columns:
var query =
(
from c in context.Customers
select new Customers()
{
ID = c.ID,
Name = c.Name,
Age = c.Age, // additional columns returning null
Height = c.Height // additional columns returning null
}
) as DataServiceQuery<Customers>;
query.BeginExecute((result) =>
Dispatcher.BeginInvoke(() =>
{
// process results from query...
// query.EndExecute(result).ToList();
}), null);
Removing all projections to return all columns fails too; I just get back the initial ID and Name fields specified earlier:
var query =
(
// No projections, just get ALL columns please!
from c in context.Customers
select c
) as DataServiceQuery<Customers>;
query.BeginExecute((result) =>
Dispatcher.BeginInvoke(() =>
{
// process results from query...
// query.EndExecute(result).ToList();
}), null);
How can I get the DataServiceQuery object to discard the previously specified projections? I don't have the option to execute the query which returns all columns first.
Issue resolved: Before executing any LINQ query, set the below MergeOption on the WCF Data Service context:
context.MergeOption = MergeOption.OverwriteChanges;
Related info:
http://social.msdn.microsoft.com/Forums/silverlight/en-US/f36d2643-661e-4048-88cf-a38df36a0b1a/linq-expand-and-dataservicequery
WCF Data Service and Silverlight: DataServiceQuery<T> will not re-perform query

Entity Framework query: object not set to an instance of an object

When calling the query.ToList() I get
object reference not set to an instance of an object
For x.Gallons, all the orders have this value set, it's not null. Also, there are 2 DProducts in the database table with proper ID. What could be wrong?
ProductSummaryCollection.Clear();
var query = from p in Repository.repository.ctx.DProduct
join fo in Repository.repository.ctx.DFuelOrder.Include("DProduct")
on p.ID equals fo.DProductID
group fo by fo.DProduct into Prod
select new DProductSummary
{
Product = fo.DProduct,
TotalGallons = (float)Prod.Sum(x => x.Gallons)
};
try
{
IList<DProductSummary> ps = query.ToList();
foreach (DProductSummary dps in ps)
ProductSummaryCollection.Add(dps);
}
catch (Exception exc)
{
}
It seems that you can't do the following 2 things:
Create a entity object, DProduct in my case inside a linq query
You cannot access a reference in a linq query even if you Include it
So you have to use the join table.Propery instead.
A working query:
var query = from fo in Repository.repository.ctx.DFuelOrder.Include("DProduct")
join p in Repository.repository.ctx.DProduct
on fo.DProductID equals p.ID
group fo by new { fo.DProductID, p.Name } into Prod
select new DProductSummary
{
ProductName = Prod.Key.Name,
TotalGallons = (float)Prod.Sum(x => x.Gallons)
};

Selecting related pairs LINQ

I'm using LINQ to manipulate a datatable. I have 3 columns - I would like group by one and then select the remaining 2 columns together. At the moment I have something like this
var query = reportDataTable.AsEnumerable()
.GroupBy(c => c["Code"])
.Select(g =>
new {
Code = g.Key,
Rank = g.Select(f => new
{ f["rank"],
f["Name"]}).ToArray()
});
but I get issues due to anonymous types. I know this syntax would work if I could reference the the column headers directly (in say a list or w/e). How can I get around this with DataTables? Cheers.
Edit:
Well I'd like to be able to reference the fields later when I come to populate the data into a different datatable:
foreach (var q in query)
{
DataRow df = dp.NewRow();
df["Code"] = q.Code;
foreach (var rank in q.Rank)
{
df[rank.name] = rank.rank;
}
dp.Rows.Add(df);
}
define your Rank fields, Also if you have a class for it, call related class constructor,
you can see this in bellow code, before ToArray.
var query = reportDataTable.AsEnumerable()
.GroupBy(c => c["Code"])
.Select(g =>
new { Code = g.Key, Rank =
g.Select(f => new { rank = f["rank"], name = f["Name"]})
.ToArray() });

linq help - newbie

how come this work
public IQueryable<Category> getCategories(int postId)
{
subnusMVCRepository<Categories> categories = new subnusMVCRepository<Categories>();
subnusMVCRepository<Post_Category_Map> postCategoryMap = new subnusMVCRepository<Post_Category_Map>();
var query = from c in categories.GetAll()
join pcm in postCategoryMap.GetAll() on c.CategoryId equals pcm.CategoryId
where pcm.PostId == 1
select new Category
{
Name = c.Name,
CategoryId = c.CategoryId
};
return query;
}
but this does not
public IQueryable<Category> getCategories(int postId)
{
subnusMVCRepository<Categories> categories = new subnusMVCRepository<Categories>();
subnusMVCRepository<Post_Category_Map> postCategoryMap = new subnusMVCRepository<Post_Category_Map>();
var query = from c in categories.GetAll()
join pcm in postCategoryMap.GetAll() on c.CategoryId equals pcm.CategoryId
where pcm.PostId == postId
select new Category
{
Name = c.Name,
CategoryId = c.CategoryId
};
return query;
}
The issue is most likely in the implementation of the query provider.
pcm.PostId == 1
and
pcm.PostId == postId
actually have a big difference. In the expression tree the first is generated as a ConstantExpression which doesnt need to be evaulated.
With the second, the compiler actually generates an inner class here (this is the _DisplayClassX that you see). This class will have a property (will most likely be the same name as your parameter) and the expression tree will create a MemberAccessExpression which points to the auto-generated DisplayClassX. When you query provider comes accross this you need to Compile() the Lambda expression and evaluate the delegate to get the value to use in your query.
Hope this helps.
cosullivan
The problem is not the linq itself,
you need to be sure that the context or provider object is able to fetch the data.
try testing the
subnusMVCRepository<Categories> categories = new subnusMVCRepository<Categories>();
subnusMVCRepository<Post_Category_Map> postCategoryMap = new subnusMVCRepository<Post_Category_Map>();
objects and see if they are populated or if they behaving as required.
you may want to search the generated code for c__DisplayClass1 and see what you can see there. some times the generated code dose some weird things.
when you step into you code check the locals and the variable values. this may also give you some clues.
Edit : Have you tried to return a List<> collection ? or an Enumerable type?
Edit : What is the real type of the item and query may not be iterable

Resources