My application is running under ASP.NET 4.0, which uses BLToolkti as ORM tool.
I have some queryable expression:
var q = db.GetTable<T>()
.Where(tb=>tb.TeamId==MyTeamId && tb.Season==MySeasonId)
.OrderByDescending(tb=>tb.Id)
.Take(20)
.Reverse()
Attempt to convert q.ToList() causes the following error:
Sequence 'Table(TeamBudget).Where(tb => ((tb.TeamId ==
value(VfmElita.DataLogicLayer.Teams.Team+TeamBudget+<>c__DisplayClass78).teamId)
AndAlso (tb.Season ==
value(VfmElita.DataLogicLayer.Teams.Team+TeamBudget+<>c__DisplayClass78).season))).OrderByDescending(tb
=> Convert(tb.Id)).Take(20).Reverse()' cannot be converted to SQL.
If I remove ".Reverse()" from the queryable object everything works fine.
What is the reason why queryable object with .Reverse() cannot be converted into SQL? Is that BLToolkit limitation? Is there any solution workaround for that?
Thank you!
It's pretty clear what the other LINQ methods convert to (where, order by, top(20)), but what would Reverse() convert to? I can't think of an SQL statement I've seen that mimics that behavior, and when you're querying the database your LINQ statement must ultimately resolve to valid SQL.
This may not be what you're going for, but one option would be to execute the query first using ToList(), then apply Reverse():
var q = db.GetTable<T>()
.Where(tb => tb.TeamId == MyTeamId && tb.Season == MySeasonId)
.OrderByDescending(tb => tb.Id)
.Take(20)
.ToList()
.Reverse();
Alternatively, you could get the count and skip that many records first, although this could be inaccurate if the number of records change between calls. Plus it's two queries instead of just one.
var totalRecords = db.GetTable<T>()
.Count(tb => tb.TeamId == MyTeamId && tb.Season == MySeasonId);
var q = db.GetTable<T>()
.Where(tb => tb.TeamId == MyTeamId && tb.Season == MySeasonId)
.Order(tb => tb.Id)
.Skip(totalRecords)
.Take(20);
Related
I'm fairly new to LINQ, but I think I'm getting the hang of it.
I'm trying to group a select statement, then order it descending. I've got pretty far just looking through other questions, but when I try to attach the OrderByDescending() function, lambda expressions I try to add are not recognized by intellisense.
var test = db.UserPokemons.Where(x => x.PkmnDataId == pokemon.Id && x.StepsToHatch == 0)
.GroupBy(n => n.User1.Country).OrderByDescending();
So, for example, .OrderbyDescending(x => x.User1.Country) does not contain a definition for User1.
Is this to do with the ordering of my statements? I think it's because I'm calling GroupBy before OrderBy, but I can't wrap my head around how to fix it.
How can I order my groups?
Oh! Nearly forgot - I only want the top 3 countries, so is there an easy way to restrict that as well?
How to use GroupBy and OrderByDescending in the same LINQ function
How to select only the top/first 3 groups
Thanks for any help!
I think this is what you want:
var test = db.UserPokemons.Where(x => x.PkmnDataId == pokemon.Id && x.StepsToHatch == 0).
GroupBy(n => n.User1.Country).Select(x=>x.First()).OrderByDescending().Take(3);
var countriesInOrder = db.UserPokemons.Where(x => x.PkmnDataId == pokemon.Id && x.StepsToHatch == 0).
GroupBy(n => n.User1.Country).OrderByDescending(x => x.Key).Take(3).ToArray();
Got it - the lambda expression needs to go to the x.Key after grouping.
(Thanks jitender!)
I am creating a query in Visual Studio for retrieving data from a SQL Server.
Can I, and if so how, use aliasing on variables in .Join()s?
I have something like:
var query =
context.tblOne
.Join(
context.tblTwo,
varOne => varOne.ParamFromVarOne,
varTwo => varTwo.ParamFromVarTwo,
(varOne, varTwo) => varOne)
Can I somehow access the "varOne" and "varTwo" objects and their parameters outside of the join? I need other parameters from varOne and two in my .Where() clause to filter the search result.
Is there perhaps another way to query for this?
I have 10 .Join()s and on those joins and after the .Where() I want to create a new JSON object.toList() using the
.Select(x => new {x.param1, x.param2, x.param3}) etc
A more abstract way of explaining what I want to do is something like:
.Where(x => x.Param1 <= compareVariable1 &&
x.Param2 >= compareVariable1 &&
y => y.Param1 == compareVariable2 &&
z => z.Param1 == compareVariable3)
In other words, a .Where() clause with multiple table-records from which I compare the column values to method parameters/arguments.
Can I perhaps concatenate the Joins and if so how do I go about this?
I am trying to return rows based on a search term that may include a space.
The code below is is generating the following error. I cannot figure out what I'm doing wrong, any suggestions?
Local sequence cannot be used in LINQ to SQL implementations of query
operators except the Contains operator.
var searchTerms = term.Split(' ').ToList();
var surveys = (from s in dc.BasicNeedsSurveys where s.Hidden ==
false orderby s.CreatedOn descending select s)
.Where(x => searchTerms.Any(y => y.Contains(x.FirstName))
|| searchTerms.Any(y => y.Contains(x.LastName))
|| searchTerms.Any(y => y.Contains(x.FEMANumber)));
according to the error message you are using linq to sql (or EF). linq to sql generate SQL query behind the scene, and you cant use a local var such as searchTerms inside an sql query. if i understand it correctly and dc.BasicNeedsSurveys is actually a data base entity (like in entity framework for example) your solution will be to first execute the sql query and then run the test if substring of search terms contains the search result. ToList is one function that can do that.
var searchTerms = term.Split(' ').ToList();
var surveys = (from s in dc.BasicNeedsSurveys where s.Hidden ==
false orderby s.CreatedOn descending select s)
.ToList()
.Where(x => searchTerms.Any(y => y.Contains(x.FirstName))
|| searchTerms.Any(y => y.Contains(x.LastName))
|| searchTerms.Any(y => y.Contains(x.FEMANumber)));
of course, there might be better ways to do that with better performance since here you are filtering the results only after you read all of them from the hard drive, but there is really not enough information in the question for that
I'm running into troubles trying to sort IQueryable of my EF Entity.
My object structure is something like this:
Item
Item.CustomFieldValue [List<CustomFieldValue>]
Item.CustomFieldValue.DefinitionID
Item.CustomFieldValue.Value
and I'm working with
IQueryable<Item>
I'd need to sort it conditionally with values having desired definition id being sorted first something like this:
queryable = queryable
.OrderBy(p => p.CustomFieldValue
.Where(p2 => p2.DefinitionID == defId)
.Select(p3 => p3.Value)
.OrderBy(p4 => p4)
);
This however throws ArgumentException "DbSortClause expressions must have a type that is order comparable.".
I indeed understand what's the exception trying to say to me, I just can't figure out on how to change this so that valid query is generated.
Any help greatly appreciated
EDIT:
To bring some more light into the issue, I want to achieve something similar that this query does
SELECT * FROM ticketnumber t, customfieldvalue c
WHERE t.id like '%00000047%' and c.ticketnumberid = t.id
ORDER BY CASE
WHEN DefinitionId = 2125 THEN 1
ELSE 2
END, c.Value ASC
Alternatively, as time is starting to become a factor for me, is there a way I could append OrderBy in string form?
You probably want to use FirstOrDefault() at the end of the end of the first OrderBy so you won't be dealing with enumerables but with values.
queryable = queryable
.OrderBy(p => p.CustomFieldValue
.Where(p2 => p2.DefinitionID == defId)
.Select(p3 => p3.Value)
.OrderBy(p4 => p4)
.FirstOrDefault()
);
Modification of Joanvo's answer did the trick, this is the working code [I've removed the inner OrderBy]
queryable = queryable.OrderBy(p => p.CustomFieldValue.Where(p2 => p2.DefinitionID == defId).Select(p3 => p3.Value).FirstOrDefault());
Is it possible within Linq in C#, to convert a string field in a database, to a long type - and use it in the query?
Here, tme is a unix time (long) - but the field in the database, targetdate - is a string.
I've tried:
var qbt = db.Calls
.Where(x => x.team == id && long.Parse(x.targetdate) <= tme);
However I get the message: LINQ to Entities does not recognize the method 'Int64 Parse(System.String)' method, and this method cannot be translated into a store expression.
I know you can convert before the linq query, but is there any way of using it WITHIN the linq query?
Thanks for any help,
Mark
try
var qbt = db.Calls.ToList()
.Where(x => x.team == id && long.Parse(x.targetdate) <= tme);
if you have many records you can limit them by team first and then call ToList like below
var qbt = db.Calls.Where(x => x.team == id).ToList()
.Where(i=>long.Parse(i.targetdate) <= tme);
Or You can use AsEnumerable
var qbt = db.Calls.AsEnumerable()
.Where(x => x.team == id && long.Parse(x.targetdate) <= tme);
This is to do with the way the Linq is translated into the backing query language, it might be easier to do a string comparison in this case, using tme.ToString(). If you pull the full collection down first, you could query like this but that means what it says: pulling down the full unfiltered (or at least less filtered) set.
You have to either change the database table to not store a string (you could create a computed column that converts it to a long or create a view if you cannot modify the existing table) or compare the value as string. The reason is that Entity Framework LINQ provider does not understand long.Parse and there is no method in SqlFunctions class for this purpose.
var stringTme = tme.ToString(CultureInfo.InvariantCulture);
var qbt = db.Calls
.Where(x => x.team == id && ((x.targetdate.Length < stringTme.Length)
|| (x.targetdate.Length == stringTme.Length && x.targetdate <= stringTme)));
You have to either change the database table to not store a string or compare the value as string. The reason is that Entity Framework LINQ provider does not understand long.Parse and there is no method in SqlFunctions class for this purpose.please use long.Parse()