How can I write this in one query?
var query = this.ObjectContext.SomeCollection.
.Where(...)
.Select(f => new {somenumber = f.somenumber});
MyType type = new MyType()
{
Sum = query.Sum(f => f.somenumber)
}
Your use of the anonymous type is completely unnecessary since you have only one property in the projection. You can simply take the query and enclose it inside the object initializer for MyType. Note that this is fine as long as you're not reusing the projection elsewhere (in which case you would pull it outside and then reuse it).
var type = new MyType {
Sum = this.ObjectContext
.SomeCollection
.Where(SomeCondition)
.Select(f => f.somenumber)
.Sum()
};
Additionally, you could reduce .Select(f => f.somenumber).Sum() to Sum(f => f.somenumber).
MyType type = new MyType {
Sum =
this.ObjectContext.SomeCollection
.Where(...)
.Select(f => f.somenumber)
.Sum() };
or even
MyType type = new MyType {
Sum =
this.ObjectContext.SomeCollection
.Where(...)
.Sum(f => f.somenumber) };
shoud do the trick
Related
Using Linq to Objects a query might need to filter based on the result of a function and return the value of that function.
For example
files.Where(x => string.IsNullOrWhiteSpace(x.getProperty(propName)))
.GroupBy(x => x.getProperty(propName));
Does the compiler recognize that the value is going to be required for grouping and keep it?
If it doesn't then there must be a way to select to an anonymous type and query the Where and GroupBy statements against that. Is it possible to do this with an anonymous type?
I am able to declare a class and use that.
class fileSelector
{
internal string prop;
internal myFile file;
}
var groups = files
.Select(x => new fileSelector() { prop = x.getProperty(propName), file = x })
.Where(x => !string.IsNullOrWhiteSpace(x.prop))
.GroupBy(x => x.prop);
But is there a way to do this with an anonymous type?
This is what I tried for an anonymous type
var groups = files.Select(x => new { x.getProperty(propName), x })
.Where(x => !string.IsNullOrWhiteSpace(x.prop))
.GroupBy(x => x.prop);
But this gives the error
Invalid anonymous type member declarator. Anonymous type members must be declared with a member assignment, simple name or member access.
Final answer
var groups = files
.Select(x => new { prop = x.getProperty(propName), file = x })
.Where(x => !string.IsNullOrWhiteSpace(x.prop))
.GroupBy(x => x.prop, x => x.file);
Does the compiler recognize that the value is going to be required for grouping and keep it?
No, since getProperty might have an intended side effect.
If it doesn't then there must be a way to select to an anonymous type and query the Where and GroupBy statements against that. Is it possible to do this with an anonymous type?
Yes. Your code should work as-it-is by just replacing new fileSelector() {...} with new {...}. Note, though, that in your code (and in the modified version using the anonymous type), the elements of the grouping are fileSelector and the anonymous type, not myFile. See Scott Chamberlain's solution for how to fix that.
Alternatively, you could use the let clause to store intermediary values:
var groups = from file in files
let prop = file.getProperty(propName)
where !string.IsNullOrWhiteSpace(prop)
group file by prop;
Does the compiler recognize that the value is going to be required for grouping and keep it?
No, it will touch the value twice.
You where actually quite close with your final example, you can do it with a annonamous type, just give names for each of the members of the anonymous type then add a element selector to make the body of the grouping the file property.
var groups = files
.Select(x => new { prop = x.getProperty(propName), file = x })
.Where(x => !string.IsNullOrWhiteSpace(x.prop))
.GroupBy(x => x.prop, x => x.file);
I have the following code:
var languages = _languageService
.GetAll()
.Select(x => (((LanguageViewModel) new LanguageViewModel().InjectFrom(x))))
.ToList();
When executing this, languages becomes, as expected, a collection of LanguageViewModel objects:
What I am trying to do is, when selecting, also convert the object's Code property to uppercase, as so:
var languages = _languageService
.GetAll()
.Select(x => (((LanguageViewModel) new LanguageViewModel().InjectFrom(x)).Code = x.Code.ToUpper()))
.ToList();
I'm expecting the languages object to have multiple LanguageViewModels in it but it looks like this:
My guess is the fact that I'm using a statement like Select(x => (new Object().Property = Value)) it selects the Property. But then, how can I return an object with one of its properties changed? Using object initializer before inject is not an option as it gets overriden, using it after the Inject is not possible, as it is not casted yet, so I got to the solution here which does not seem to work. Any advice greatly appreciated.
You can't write the lambda body as a single expression that does what you want, but you don't need to. You can put multiple statements in a lambda:
var languages = _languageService
.GetAll()
.Select(x => {
var lvm = (LanguageViewModel)new LanguageViewModel().InjectFrom(x);
lvm.Code = x.Code.ToUpper();
return lvm;
})
.ToList();
Your Select line could be rewritten to
.Select(x =>
{
var vm = new LanguageViewModel().InjectFrom(x);
vm.Code = vm.Code.ToUpper();
return vm;
})
I have a filtered list which returns all the distinctIds from MenuTable
var _parentList = _employee.Designation.Role.MenuRoles
.Select(x => new
{
MenuParentID = x.Menu.ParentID
})
.DistinctBy(x => x.MenuParentID)
.OrderBy(x => x.MenuParentID)
.ToList();
I want to select all the items from menutable which is in _parentList
This is what i have tried and an error is coming on _parentList.Contains(x.Id) which says Best overloaded match for System.Generic.contains has some invalid arguments.
MenuParentList = _db.Menus.Where(x => _parentList.Contains(x.Id))
.Select(x => new SMS.Models.ViewModel.DashboardVM.MenuParent
{
MenuParentID = x.Id,
MenuParentName = x.MenuName
})
.ToList()
Any help will be appreciated
Cf. this code:
.Select(x => new
{
MenuParentID = x.Menu.ParentID
})
This results in a list of anonymous objects with one property called MenuParentID, instead of a list of integers. The compiler creates a type for you that structurally looks like this (note that the compiler generates a non-usable class name behind the scenes instead of AnonymousType1, but you get the idea):
class AnonymousType1
{
public int MenuParentID {get;set;}
}
And _parentList would be of type List<AnonymousType1>.
Adjust your code as follows:
var _parentList = _employee.Designation.Role.MenuRoles
.Select(x => x.Menu.ParentID)
.Distinct()
.OrderBy(id => id)
.ToList();
Now _parentList is of type List<int>.
You can read more about the concept of anonymous types on msdn: https://msdn.microsoft.com/en-us/library/bb397696.aspx
This is my a linq query that filter tasks by range name then group them by language.
var transTasks = taskData
.Where(t => t.RangeName == rName)
.GroupBy(t => t.CultureID)
.Select(g => new { language = g.Key, tasks = g });
Now I'd like to use the same query for a different grouping. Instead of grouping by CultureID, I'd like to group by TaskOrder.
So I've create variables like this
Func<QuoteTaskInfo, bool> predicate = null
if(tasktype == "translation")
{
groupPredicate = t => t.CultureID;
{
else
{
groupPredicate = t => t.TaskOrder;
}
I'm getting the following error: "Cannot convert expression ... because some return type are not convertible to the delegate return type".
Any help on how to write a delegate that would return a bool?
The same goes with Select(). If the criteria is task order, then the key for the select should be TaskOrder instead of language.
Thanks for helping
I'm trying to make a linq GroupJoin, and I receive the fore mentioned error. This is the code
public Dictionary<string, List<QuoteOrderline>> GetOrderlines(List<string> quoteNrs)
{
var quoteHeadersIds = portalDb.nquote_orderheaders
.Where(f => quoteNrs.Contains(f.QuoteOrderNumber))
.Select(f => f.ID).ToList();
List<nquote_orderlines> orderlines = portalDb.nquote_orderlines
.Where(f => quoteHeadersIds.Contains(f.QuoteHeaderID))
.ToList();
var toRet = quoteNrs
.GroupJoin(orderlines, q => q, o => o.QuoteHeaderID, (q => o) => new
{
quoteId = q,
orderlines = o.Select(g => new QuoteOrderline()
{
Description = g.Description,
ExtPrice = g.UnitPrice * g.Qty,
IsInOrder = g.IsInOrder,
PartNumber = g.PartNo,
Price = g.UnitPrice,
ProgramId = g.ProgramId,
Quantity = (int)g.Qty,
SKU = g.SKU
}).ToList()
});
}
I suspect this is the immediate problem:
(q => o) => new { ... }
I suspect you meant:
(q, o) => new { ... }
In other words, "here's a function taking a query and an order, and returning an anonymous type". The first syntax simply doesn't make sense - even thinking about higher ordered functions, you'd normally have q => o => ... rather than (q => o) => ....
Now that won't be enough on its own... because GroupJoin doesn't return a dictionary. (Indeed, you don't even have a return statement yet.) You'll need a ToDictionary call after that. Alternatively, it may well be more appropriate to return an ILookup<string, QuoteOrderLine> via ToLookup.