var sortQ = filterQ; // <--- update
if (iSortingCols > 0)
{
sortQ = (sortDirs[0] == "asc") ?
sortQ.OrderBy((d) => d.GetColumnData()[sortCols[0]]) :
sortQ.OrderByDescending((d) => d.GetColumnData()[sortCols[0]]);
if (iSortingCols > 1)
{
for (int i = 1; i < iSortingCols; i++)
{
sortQ = (sortDirs[i] == "asc") ?
sortQ.ThenBy(d => d.GetColumnData()[sortCols[i]]) :
sortQ.ThenByDescending(d => d.GetColumnData()[sortCols[i]]);
}
}
}
The compiler underlines the two results of the ternary operator inside the for loop, saying that IEnumerable<...> doesn't have a method overload called ThenBy (and similarly for ThenByDescending), but the sortQ will be an IOrderedEnumerable<...> in that block. Why isn't C# type inference picking that up?
Update: for those who might have been confused before, what I left out of the original snippet was that I was assigning sortQ to the result of another query which forced the type inference engine to type sortQ as an IEnumerable<..>, which of course is what was screwing up my example. The answer below is the way around this. Thanks to #Marc for reading between the lines.
I'm guessing sortQ is IEnumerable<T>; you need an IOrderedEnumerable<T> to use ThenBy; fortunately, your first OrderBy returns this, so just catch that:
var result = (sortDirs[0] == "asc") ?
sortQ.OrderBy((d) => d.GetColumnData()[sortCols[0]]) :
sortQ.OrderByDescending((d) => d.GetColumnData()[sortCols[0]]);
if (iSortingCols > 1)
{
for (int i = 1; i < iSortingCols; i++)
{
result = (sortDirs[i] == "asc") ?
result.ThenBy(d => d.GetColumnData()[sortCols[i]]) :
result.ThenByDescending(d => d.GetColumnData()[sortCols[i]]);
}
}
Related
I'm working right now to build LINQ up to the side where it needs to retrieve some information from the user about how many applications as you have got to be friends. - user exists in tablen.
venner Numberoffriends = db.venners.Where(UseridFriends => UseridFriends.To == 1 && UseridFriends.Godkendt == 0).Count();
if(Numberoffriends != null)
{
//true
}
it is such that it now makes mistakes here
db.venners.Where(UseridFriends => UseridFriends.To == 1 && UseridFriends.Godkendt == 0).Count();
ERROR ARE: The type 'int' can not be implicitly converted to 'LinqData.venner'
The error is because the return type of the Count() extension method is int, and you are trying to assign the return value to a LinqData.venner.
There is no implicit conversion from int to LinqData.venner, so that is the source of your error.
You can confirm this by refactoring your code into the following equivalent code:
int count = db.venners.Where(UseridFriends => UseridFriends.To == 1 && UseridFriends.Godkendt == 0).Count();
venner Numberoffriends = count;
if ( Numberoffriends != null )
{
//true
}
which will transfer your compilation error to the
venner Numberoffriends = count;
line.
It seems from your code that instead of having a count (using the Count() method), you want something like FirstOrDefault() or ToList(). This will enable you to do something with the venner object(s) you get.
I think the following would build, but I'm not sure about your intention and hence if it's what you want:
List<venner> venners = db.venners
.Where(UseridFriends => UseridFriends.To == 1 && UseridFriends.Godkendt == 0)
.ToList();
if ( venners.Count != 0 )
{
//true
// do something with venners here
}
What are you trying to do with your linq?
I've got a method which can accept an optional int? value as a number of items to Take from a collection. I want to return all items if a null value is passed. Right now I have to duplicate my query to accomplish this
if(take == null)
{
x = db.WalkingDeadEps.Where(x => x.BicyclesCouldHaveSavedLives == true).ToList()
}
else
{
x = db.WalkingDeadEps.Where(x => x.BicyclesCouldHaveSavedLives == true).Take(take).ToList()
}
Is there a simpler way? Something like this?
.Take(take != null ? take : "all")
with Linq you have the option to store your query in variables. it will not be executed until you call ToList or equivalent methods on it.
var query = db.WalkingDeadEps.Where(x => x.BicyclesCouldHaveSavedLives == true);
x = take.HasValue ? query.Take(take.Value).ToList() : query.ToList();
I have a problem trying to implement a filtering expression to filter a list of entities :
The LINQ expression node type 'Invoke' is not supported in LINQ to
Entities.
This is the code :
public IList<DocumentEntry> GetDocumentEntriesForRateAdjustmentTry2(
string username, Rate rate, List<RatePeriod> ratePeriods)
{
var dimensionLibManager = new DimensionLibManager();
var currentVersionRateGroups = rate.CurrentRateVersion.RateGroups.ToList();
Expression<Func<DocumentEntry, IList<RateGroup>, int, bool>> dimensionMatchesExpression =
(documentEntry, rateGroups, dimensionInfoId) =>
rateGroups.Any(
rg =>
rg.Dimension1.All(character => character == '*')
||
documentEntry.DocumentEntryDimensions.Any(
ded =>
ded.DimensionInfo.Position == dimensionInfoId
&&
dimensionLibManager.GetDimensionSegments(rate.CompanyId, username, dimensionInfoId, ded.Value).Any(
seg => ded.Value.Substring(seg.SegmentStart, seg.SegmentLength) == seg.SegmentValue)));
var dimensionMatches = dimensionMatchesExpression.Compile();
var documentEntries = this.ObjectSet.Where(de => dimensionMatches(de, currentVersionRateGroups, 1));
var result = documentEntries.ToList(); // The error happens here.
return result;
}
I suspect that dimensionMatchesExpression cannot be traduced into SQL because inside it calls another library's method (dimensionLibManager.GetDimensionSegments) to filter documents based on specific parameters.
Is there a way (other than using LinqKit or any additionnal extention library) that I can make this work ?
The reason why I want to use an Expression to act as a filter is because, ultimately, I would like to to this :
var documentEntries = this.ObjectSet.Where(de =>
dimensionMatches(de, currentVersionRateGroups, 1)
&& dimensionMatches(de, currentVersionRateGroups, 2)
&& dimensionMatches(de, currentVersionRateGroups, 3)
&& dimensionMatches(de, currentVersionRateGroups, 4));
Also, how can I actually debug that kind of problem ? The error message is pretty vague. How can I track down the exact node that is causing the error ?
I suspect this is the issue.
var documentEntries = this.ObjectSet.Where(de => dimensionMatches(de, currentVersionRateGroups, 1));
I don't think that row number works with Linq2EF.
public IList<DocumentEntry> GetDocumentEntriesForRateAdjustmentTry2(
string username, Rate rate, List<RatePeriod> ratePeriods)
{
var dimensionLibManager = new DimensionLibManager();
var currentVersionRateGroups = rate.CurrentRateVersion.RateGroups.ToList();
Expression<Func<DocumentEntry, int, bool>> dimensionMatchesExpression =
(documentEntry, rateGroups, dimensionInfoId) =>
currentVersionRateGroups.Any(
rg =>
rg.Dimension1.All(character => character == '*')
||
documentEntry.DocumentEntryDimensions.Any(
ded =>
ded.DimensionInfo.Position == dimensionInfoId
&&
dimensionLibManager.GetDimensionSegments(rate.CompanyId, username, dimensionInfoId, ded.Value).Any(
seg => ded.Value.Substring(seg.SegmentStart, seg.SegmentLength) == seg.SegmentValue)));
var documentEntries = this.ObjectSet.Where(dimensionMatchesExpression);
var result = documentEntries.ToList(); // The error happens here.
return result;
}
Although I don't understand why you want to use an expression to do this. You could just inline it all...
Just realised a few days ago the solution to your problem...bit of a hack...
public Expression<Func<DocumentEntry, int, bool>> CreateWhereClause(stuff);
public IList<DocumentEntry> GetDocumentEntriesForRateAdjustmentTry2(
string username, Rate rate, List<RatePeriod> ratePeriods)
{
using(var db = new Context())
{
IQueryable<DocumentEntry> foo = db.Foos;
foreach(var i =0; i <4; i++)
{
foo = foo.Where(DocumentEntry(i));
}
}
}
How would I convert the following using LINQ?
foreach (int[] arr in jaggedArray)
{
if (arr[7] == 1)
{
if (!CheckThis(arr))
boolSuccess = false;
else
intCount++;
}
}
Something like this:
var filtered = jaggedArray.Where(arr => arr[7] == 1);
var intCount = filtered.Where(ar => CheckThis(ar)).Count()
var boolSuccess = filtered.Count() == intCount;
Nested query has to be written for the same logic or else the source code logic has to be simplified first to get a simple query
I use ReSharper, which suggests when a Linq expression is better - and performs the translation. Sometimes I keep my code though, when the Linq becomes too complex and hard to understand.
I believe this would work: First, it sets intCount by getting all of the items that satisfy arr[7]==1 and pass the CheckThis() method. That should be your intCount value.
Then, if the value in intCount doesn't match the length of the array, at least one thing failed, so you can set boolSuccess to false.
Please note that I consider this solution to be more clever, and less readable. Less readable is always a bad thing. Plus, you could refactor your existing method easily, whereas doing it this way would be much harder to refactor due to the Cleverness Factor.
intCount = jaggedArray.Where(x => x[7] == 1).Where(CheckThis).Count();
if (intCount != jaggedArray.Length) boolSuccess = false;
You can use Array.ForEach, although I think what you started with is actually clearer
Array.ForEach(jagged, arr =>
{
if (arr[7] == 1)
{
if (!CheckThis(arr))
{
boolSuccess = false;
}
else
{
intCount++;
}
}
});
intCount += jaggedArray
.Where(arr => arr[7] == 1)
.Select(arr =>
{
int val = CheckThis(arr) ? 1 : 0;
if (val == 0) {boolSuccess = false;}
return val;
}).Sum()
I am using c#.net
I have two textboxes which if !empty need to be part of a WHERE clause within a LINQ query.
Here is my code
var result = from a in xxxx select a;
if(!string.IsNullOrEmpty(personName))
{
return result.Where(a >= a.forename.Contains(personName) || a.surname.Contains(personName)
}
else if(!string.IsNullOrEmpty(dateFrom))
{
return result.Where(a >= a.appStartDateTime >= dateFrom.Date)
}
else if(!string.IsNullOrEmpty(personName) && !string.IsNullOrEmpty(dateFrom))
{
return result.Where(a >= a.forename.Contains(personName) || a.surname.Contains(personName) && a.appStartDateTime >= dateFrom.Date);
}
I thought this would work but it doesn't like the .Where and I cant access the 'a' for example a.forename (The name 'a' does not exist in the current context)
What am I going wrong, or can this not actually be done?
Thanks in advance for any help.
Clare
Instead of this:
result.Where(a.forename.Contains(personName))
Try this:
result.Where(a => a.forename.Contains(personName))
You appear to be missing the Lambda operator (=>).
try this
var result = from a in xxxx select a
where (string.IsNullOrEmpty(personName) || a.forename.Contains(personName)
|| a.surname.Contains(personName))
&& (string.IsNullOrEmpty(dateFrom)
|| a.appStartDateTime >= DateTime.Parse(dateFrom).Date);
dateFrom appears to be a string so you have to parse it to get a date time.
This logic should work but I have not tested it. I could be wrong.
You seem to only care if the forename or surname contain personName if the personName is not null or empty. So you can rewrite it to return things if the personName is null or empty or the fore or sur name contains person name. Since the || operator is short circuiting it will not check Contains if the personName is null or empty.
You can also combine the predicates and make the logic shorter and easier to read:
var result = from a in xxxx select a;
if (!string.IsNullOrEmpty(personName))
result = result.Where(a => a.forename.Contains(personName) || a.surname.Contains(personName)
if (!string.IsNullOrEmpty(dateFrom))
result = result.Where(a >= a.appStartDateTime >= dateFrom.Date)
return result;
This method of combining predicates works well with 'AND' conditions. If you need to 'OR' conditions, it's a little bit more involved. Thankfully, Joe Albahari has created PredicateBuilder (as part of LINQKit) that helps with this greatly.
Hope this helps.
..or with just one exit point:
var result = from a in xxxx select a;
Func<string, bool> func = null;
if(!string.IsNullOrEmpty(personName))
{
func = (a) => {a.forename.Contains(personName) || a.surname.Contains(personName)};
}
else if(!string.IsNullOrEmpty(dateFrom))
{
func = (a) => {a.appStartDateTime >= dateFrom.Date};
}
else if(!string.IsNullOrEmpty(personName) && !string.IsNullOrEmpty(dateFrom))
{
func = (a) => {a.forename.Contains(personName) || a.surname.Contains(personName) && a.appStartDateTime >= dateFrom.Date;};
}
return result.Where(func);