LINQ to Entities grouped logical operations in Where - linq

I'm trying to execute the following linq query and it seems to be ignoring order of operations. (Parentheses first)
var result = _repo.Transactions.Where(t =>
t.DateEntered > EntityFunctions.AddDays(DateTime.Now, -7)
&& ( t.TranDesc != "BALANCE FORWARD" && t.Withdrawl == 0 && t.Deposit == 0 ) );
Here's the where clause that generates:
WHERE ([Extent1].[dateentered] > (DATEADD (day, -7, SysDateTime())))
AND (N'BALANCE FORWARD' <> [Extent1].[TranDesc])
AND (cast(0 as decimal(18)) = [Extent1].[Withdrawl])
AND (cast(0 as decimal(18)) = [Extent1].[Deposit])
Any ideas what I'm doing wrong?
EDIT:
This is actually what I wanted and it solved my problem. Just didn't think it all the way though. Thanks.
var result = _repo.Transactions.Where(t =>
t.dateentered > EntityFunctions.AddDays(DateTime.Now, -7)
&& ((t.TranDesc == "BALANCE FORWARD" && (t.Withdrawl != 0 || t.Deposit != 0))
|| (t.TranDesc != "BALANCE FORWARD")));

There is no difference between a && (b && c && d) and a && b && c && d, and that's why parentheses within generated SQL are not exactly the same as in your LINQ query. But at the end there is no difference between these queries.

Related

Having trouble trying to order using linq

I am trying to order by start date(s.StartDate). Below is my code so far, my understanding is that I should be adding .orderby(s.StartDate) somewhere but I don't think I'm even taking the correct route now as I have tried many ways.
var query = from s in context.SessionSearch
where s.Children == 0 && s.IsPublic == isPublic
select s;
var query = from s in context.SessionSearch
where s.Children == 0 && s.IsPublic == isPublic
if (startDate != null)
{
query = query.Where(s => s.StartDate >= startDate && s.StartDate <= endDate);
}
You should be able to start with the "without startdate" option - you have a couple of options here - either declare the type of the query specifically:
IQueryable<SessionSearch> query = from s in context.SessionSearch
where s.Children == 0 && s.IsPublic == isPublic
order by s.StartDate
select s;
And then as you've tried, add the additional where clause to the query if there's a start date passed in:
query = query.Where(s => s.StartDate >= startDate && s.StartDate <= endDate);
This means that you would not be able to add further ordering via the ThenBy methods.
Alternatively, you can add the order by clause after you've finished adding the where clauses:
var query = from s in context.SessionSearch
where s.Children == 0 && s.IsPublic == isPublic
select s;
if (startDate != null) {
query = query.Where(s => s.StartDate >= startDate && s.StartDate <= endDate);
}
query = query.OrderBy(s => s.StartDate);
Props to JonSkeet for pointing these out.

search fails with maxid (ulong.max) and sinceid set, but separately it works

the following query works ok if you comment out either the SinceID or the MaxID clause, but when both are included a "bad url" exception is generated.
var maxId = ulong.MaxValue;
var sinceId = (ulong)341350918903701507;
var searchResult =
(
from search in ctx.Search
where search.Type == SearchType.Search &&
search.ResultType == ResultType.Mixed &&
search.Query == "red wedding" &&
search.SinceID == sinceId &&
search.MaxID == maxId &&
search.IncludeEntities == false &&
search.Count == 200
select search).SingleOrDefault();
If you look at the query result in Fiddler, you'll see that the response is:
{"errors":[{"code":195,"message":"Missing or invalid url parameter"}]}
I can't respond to why Twitter wouldn't accept the query with both SinceID and MaxID. However, the query is formed correctly and there isn't any documentation describing constraints on the relationship between these two parameters for this particular scenario. The purpose of the MaxID is to be the id of the highest tweet to return on the next query. Both MaxID and SinceID are intended to help you page through data. I wrote a blog post on how to do this:
Working with Timelines with LINQ to Twitter
I seem to have the same problem as you are, so the only solution I have was to do it manually, so first I retrieved the the first list setting the sinceId value to the one I have like this:
var searchResult =
(
from search in TwitterCtx.Search
where search.Type == SearchType.Search &&
search.Query == query &&
search.Count == pageSize &&
search.IncludeEntities == true &&
search.ResultType == ResultType.Recent &&
search.SinceID == sinceId
select search
).SingleOrDefault<Search>();
resultList = searchResult.Statuses;
Then I have to search for other tweets (the case when new tweets count is more the pageSize) so I had a while loop like this:
ulong minId = ulong.Parse(resultList.Last<Status>().StatusID) - 1;
List<Status> newList = new List<Status>();
while (minId > sinceId)
{
resultList.AddRange(newList);
searchResult =
(
from search in TwitterCtx.Search
where search.Type == SearchType.Search &&
search.Query == query &&
search.Count == pageSize &&
search.IncludeEntities == true &&
search.ResultType == ResultType.Recent &&
search.MaxID == minId &&
search.SinceID == sinceId
select search
).SingleOrDefault<Search>();
newList = searchResult.Statuses;
if (newList.Count == 0)
break;
minId = ulong.Parse(newList.Last<Status>().StatusID) - 1;
}
Now for some reason here you can use both sinceId and maxId.
Just in case anyone else comes across this, I encountered this issue when the MaxId was an invalid Tweet Id.
I started off using zero but ulong.MaxValue has the same issue. Switch it out with a valid value and it works fine. If you're not using SinceId as well it seems to work fine.
I used to get same error "Missing or invalid url parameter", but as per Joe Mayo's solution, I have additionally added if(sinceID < maxID) condition before do while loop, because the query throws above error whenever maxID is less than sinceID, I think which is incorrect.
if (sinceID < maxID)
{
do
{
// now add sinceID and maxID
searchResponse =
await
(from search in twitterCtx.Search
where search.Type == SearchType.Search &&
search.Query == "from:#" + twitterAccountToDisplay + " -retweets" &&
search.Count == count &&
search.SinceID == sinceID &&
search.MaxID == maxID
select search)
.SingleOrDefaultAsync();
if (searchResponse == null)
break;
if (searchResponse.Count > 0 && searchResponse.Statuses.Count > 0)
{
newStatuses = searchResponse.Statuses;
// first tweet processed on current query
maxID = newStatuses.Min(status => status.StatusID) - 1;
statusList.AddRange(newStatuses);
lastStatusCount = newStatuses.Count;
}
if (searchResponse.Count > 0 && searchResponse.Statuses.Count == 0)
{
lastStatusCount = 0;
}
}
while (lastStatusCount != 0 && statusList.Count < maxStatuses);
//(searchResponse.Count != 0 && statusList.Count < 30);
}

Converting a Query to LINQ

How can I convert the following query in a Linq with Lambda ?
SELECT DISTINCT Registro, COUNT(Registro) as qnt
FROM XML_Relatorio
WHERE Arquivo = 'redenet.xml'
AND TipoErro <> 'Imovel Inserido'
AND TipoErro <> 'TI'
AND DataHora BETWEEN '01-01-2012' AND '02-01-2012'
GROUP BY Registro
ORDER BY Registro
I'm trying the following code, but I need some help to build the LINQ with Lambda
IQueryable<XML_Relatorio> quantidadeErro = db.XML_Relatorios
.Where(a => a.Arquivo == "redenet.xml"
&& a.TipoErro != "Imovel Inserido"
&& a.TipoErro != "TI");
Supposing the DataHora field is of Date or DateTime type.
// parse the strings to datetime
var start = DateTime.Parse("01-01-2012");
var end = DateTime.Parse("02-01-2012");
IQueryable<XML_Relatorio> quantidadeErro = db.XML_Relatorios
.Where(a => a.Arquivo == "redenet.xml"
&& a.TipoErro != "Imovel Inserido"
&& a.TipoErro != "TI"
// and compare them...
&& a.DataHora > start && a.DataHora < end);

Linq to nHibernate - exclude elements without child elements

var locations = (from location in session.Query<Location>()
where
(location.MB_ID == 0 || location.MB_ID == null) &&
(location.hide != "Y" || location.hide == null) &&
(location.locationNameRaw != "" && location.locationNameRaw != null) &&
((location.isIPCapableText != "" && location.isIPCapableText != null) || (
(location.ISDNNumber1 != null && location.ISDNNumber1 != "") ||
(location.ISDNNumber2 != null && location.ISDNNumber2 != "") ||
(location.ISDNNumber3 != null && location.ISDNNumber3 != "") ||
(location.ISDNNumber4 != null && location.ISDNNumber4 != "") ||
(location.ISDNNumber5 != null && location.ISDNNumber5 != "") ||
(location.ISDNNumber6 != null && location.ISDNNumber6 != "")
))
&& (location.privateRoom == "N" || location.privateRoom == "" || location.privateRoom != null)
&& (
from lll in session.Query<LocationLonLat>()
where
location.locationID == lll.locationId
select lll.locationId
).Any()
&& (location.LastUpdatedTime > lastUpdateTime)
&& location.LocationTimes.Count() > 0
/*&& (
from lt in session.Query<LocationTimes>()
where
location.locationID == lt.LID
select lt.LID
).Any()*/
select location
)
.ToList();
There is a relationship between Location (1) and LocationTimes (many), and I only want to return a dataset of locations that have at least one LocationTime record.
I tried a couple of things...
When I add the line:
&& location.LocationTimes.Count() > 0
or if I add the line:
&& (
from lt in session.Query<LocationTimes>()
where
location.locationID == lt.LID
select lt.LID
).Any()
The underlying connection was closed: A connection that was expected to be kept alive was closed by the server.
I suspect that this may because of the size of the dataset or something...
Is there a better way of doing this? Like with a 'left outer join' or something?
I think a simple join should do it.
from locationTime in Query<LocationTime>()
join location in Query<Location>() on locationTime.Location.LocationId equals location.LocationId
join locationLat in Query<LocationLat>() on location.LocationLat.LocationLatId equals locationLat.LocationLatId
where ...
select location;

Silly question about how you format long if statements

On long if statements where they take up more than one line, do you put the conditions like AND or OR on a new line like this:
if (something
&& something else)
Or like this:
if (something &&
something else)
For complex conditions, consider extracting it into a function or a variable:
if (complexCondition(foo)) { ..
As a bonus, the name of the function or variable can be used to communicate what the condition means. This makes your code easier to read.
I typically do it the second way, since I can line up the statements. However, either way is fine when you're writing code, as long as you're consistent.
I prefer a rendition of the first. My reasoning is that deleting a condition via cut/paste/comment for any testing purposes is easier. It's a lot easier to comment out a line than it is to delete the and from the line above and comment out a line. This is more when I'm doing where clauses in SQL than in an if statement in any other given language, but is similar.
Given my druthers, I'd avoid long if tests in the first place. I'd rather do something like:
bool fTest1 = A == B ;
bool fTest2 = C ;
bool fTest3 = f(1,2,3) ;
bool fSuccess = ( fTest1 | ftest2 ) & fTest3 ;
if ( fSuccess )
...
Otherwise something like this:
if ( A == B
&& ( C == D
|| E == F
)
&& Z > Y
) {
...
}
else
{
...
}
YMMV, of course.
The former is far easier to debug, test, log, etc.
I usually format using the IDE formatter and then rearrange a bit to make it look beautiful.
I'm working in VSC and recently managed to not only write, but make readable very long conditions in nested if statements. Just use brackets and new lines like this. It should make automatic indentations:
foreach ($panstwa as $key => $value) {
if (is_object($value)) {
if (
(
($value->checkbox1 === true) && (is_string($value->panstwoZListy)) && ($value->panstwoZListy !== 'none') && ($value->panstwo === '') && ($value->panstwoZListy !== '')
) ||
(
(
($value->checkbox2 === true &&
($value->checkbox2_1 === true || $value->checkbox2_2 === true || $value->checkbox2_3 === true || $value->checkbox2_4 === true || $value->checkbox2_5 === true || $value->checkbox2_6 === true)
) ||
($value->checkbox3 === true &&
($value->checkbox3_1 === true || $value->checkbox3_2 === true)
) ||
($value->checkbox4 === true &&
(
(
($value->checkbox4_1 === true || $value->checkbox4_2 === true || $value->checkbox4_3 === true || $value->checkbox4_4 === true || $value->checkbox4_5 === true || $value->checkbox4_6 === true || $value->checkbox4_7 === true) && ($value->checkbox4_8 === false)
) ||
(
($value->checkbox4_1 === false && $value->checkbox4_2 === false && $value->checkbox4_3 === false && $value->checkbox4_4 === false && $value->checkbox4_5 === false && $value->checkbox4_6 === false && $value->checkbox4_7 === false) && ($value->checkbox4_8 === true) && (sprawdzRegexTextInput($value->prawnieUzasadnionyInteres)) && (is_object($value->dokumentacjaOceny) || is_string($value->dokumentacjaOceny))
)
)
)
) &&
(is_string($value->panstwo)) && ($value->panstwoZListy === 'none') && ($value->panstwo !== '') && (sprawdzRegexTextInput($value->panstwo)
)
) &&
((is_int($value->panstwoid) && is_numeric($value->panstwoid)) || (is_bool($value->panstwoid) && $value->panstwoid === false)) &&
(is_bool($value->zmiana))
) {
echo "ok";
//nie robiÄ™ nic
} else {
$flagaPanstwa = false;
}
} else {
$flagaPanstwa = false;
}
}

Resources