I am trying to check if a field is Null or Empty.
I have the following script:
return db.Clients.Where(a => string.IsNullOrEmpty(a.ClientName) == false)
.OrderBy(a => a.ClientName);
It seems to work as expected. I was wondering if the above is the most efficient or if there may be some gottchas that I may not be aware of in using what I have above that may lead to issues.
AFAIK, String.IsNullOrEmpty cannot be translated, therefor it can be faster to check for null and empty manually and seperately.
Related
I've noticed a slight problem with how my API is working where I'm using Spring Data JPA.
My query looks something along the lines of:
#Query("SELECT p.id AS id, COUNT(l) AS likes FROM Post p LEFT JOIN Like l ON l.post = p WHERE p.location.id = ?1")
My actual query is bigger, this this contains everything necessary to explain what the issue is. This query will return a list, but assume the location does not exist, it should return null or an empty list, correct? Oh, how wrong you are, my sweet summer child!
This query will instead always return a list of at least one element, regardless of whether or not there are any posts linked to said location.
[{"id": null, "likes": 0}]
That is what the result looks like when serialized to JSON. I am not quite sure what to do about this little predicament, as I obviously don't want to return a list with faulty data, but needing to use processing to filter out duds also seems dumb and unnecessary.
Is there any way to prevent this that I've yet to find? If it is of any relevance, I am using projections currently for my responses.
What I've tried so far:
Adding a not null condition for fields. Does not work, ignored by COUNT.
Adding constraints to all fields #NotNull. Does not work, will still become null.
For what it's worth, I've tried different kinds of joins, though anything but LEFT JOIN doesn't make much sense.
I haven't been able to find any other case which resembles this either, although it most likely exists, but is drowned out by everything else. I'm not quite sure what can be done in this regard, so I'm curious if it's just a quirk with the framework, or if there is an actual solution.
It might be possible to solve through native queries, but I would prefer not to use them.
I'm no SQL expert but I believe that a left join will give you this result if the ID does not exist.
Have you run the query in your DB? Doesn't it give you one row in your result set for IDs that do not exist?
I believe this is intended to say there is a 0 match.
You might want to validate your query before running it. Meaning checking that the location exists first.
As the issue is inherently due to a COUNT and CASE keyword in my real query, resulting in there always being at least one row, and I can't find any method of doing this automatically, the solution I've used is the following:
List<Item> items = repository.customQuery(id);
if (0 < items.size() && null == items.get(0).getId()) {
items.remove(0);
}
The first condition is arbitrary as I know there is always at least one entry, but is done just as a safety measure. A try-catch block would do the trick as well. In the case where you use a primitive int instead of Integer, you'd need to initialize the value in the constructor to something which would normally never be present in the database, such as -1.
If anyone knows of a better method, I'd love to know about it.
First of all, I know title of my question is ambiguous, but I don't know how to say. You'll know when you see my example.
In SQL queries, you can apply dynamic conditions with '1=1'.
Let me give example.
select * from PROD.EMPLY
WHERE 1=1
AND ( NAME = 'JOHN' OR NAME = 'MARY' OR NAME = 'KEVIN') ;
As above, I want to apply filters like below.
BooleanFilter BF = new BooleanFilter();
TermsFilter tf1 = new TermsFilter();
TermsFilter tf2 = new TermsFilter();
//tf1 => 1=1
//tf2 => name condition
tf2.addTerm("name", "JOHN");
tf2.addTerm("name", "MARY");
tf2.addTerm("name", "KEVIN");
BF.add(new FilterClause(tf1, Occur.MUST)); // 1=1 condition
BF.add(new FilterClause(tf2, Occur.MUST)); // name condition
But the results aren't matched as I expected.(no hits)
As I know, it's because there's no null/empty search method in Lucene.
I also checked whether I can switch BooleanFilter/TermsFilter with MatchAllDocsQuery.
However in my case, my Lucene version is so old(2.3.2) that there's no MatchAllDocsQuery in my version, and I don't want filter's conditions to affect to lucene's scoring.
I searched within stackoverflow and google, but there's no case which matches my situation.
Any help would be very appreciated and thanks for reading.
I didn't want to answer myself, but I hope that my poor solution may help/inspire someone who have same trouble.
In my case, as above, my Lucene version is so lower version that many filters are restricted.
However, I didn't want to use query, because I didn't want filters to affect to scoring.
So, I cleared myself by "manual" filter.
My development language was Java, so I used contains method.
To brief my solution, like below.
Search Lucene with AS-IS method.
Within result, compare with contains method (I added this step.)
example :
if (result.contains("KEVIN") ) {
isFilteredResult = true;
} else if (result.contains("JOHN") ) {
isFilteredResult = true;
}
...
The only results which contains condition keywords are displayed.
I was worried about this solution because this way is done with not Lucene but Java step. So, I guessed so much memory would be consumed.
However, the perfomance isn't bad as I was worried, and the users are satisfied with both performance and results.
I know this solution isn't good way, but if the condition is so restricted, this way would also a solution.
Thanks for reading.
And if there's better solution, please let me know.
Does anyone know how to check for an unassigned string in uipath? Uipath seems to crash when an if statement looks for a null string. Not sure how to handle that. String.empty doesn't seem to work, and if the string is unassigned uipath stops logging and nothing happens.
There are many different approaches and ideas, but – according to me – what you can do is:
Always make sure before to define any variable by default, initialize it with empty strings(""). So it will be easy to check it with equal operator as well.
The Other approaches you can take in Uipath is based on .Net So u can use it's Is Nothing.
You can also use .Net String.IsNullOrEmpty Method (String) Method.
To check if a string variable is Null, you need to use either an If or Decision activity. The condition of those should be:
a is Nothing
This will return true if variable a is null and false otherwise
Best way to check string has value or not -->
These are some of the ways it can be checked.
1.
String.IsNullOrEmpty(yourString)
2.
yourString.Equals("")
3.
yourString.Equals(Nothing)
4.
yourString is Nothing
5.
String.IsNullOrWhiteSpace(yourString)
There are logical OR, AND and NOT to combine the different checks and they can clubbed together to check the best way to find out blank, null and whitespace string.
You can compare the string using:
Convert.ToString(DBNULL.Value)
We can check whether String is null with the following Syntax
String.IsNullOrWhiteSpace("Name_of_the_variable")
It will return boolean value
My suggestion is using the following method in UiPath
An If/Decision activity with the condition string.IsNullOrEmpty() making use of the IsNullOrEmpty() method
The best and easiest way will be the following:
String.IsNullOrWhiteSpace(stringVariableName)
Can I write this query shorter and/or more elegantly using the AREL/ActiveRecord API?
Foo.where("(bar is not null and bar != '') or (baz is not null and baz !='')")
You can do an OR operator with Arel directly but the syntax isn't hugely pretty and can get a bit hard to read. Here is what it would look like in arel:
foo = Foo.arel_table
Foo.where(foo[:bar].not_eq(nil).and(foo[:bar].not_eq('')).or(foo[:baz].not_eq(nil).and(foo[:baz].not_eq(''))))
I'd suggest looking at the squeel gem. It gives you access to more arel functionality in active record. Your query would like like:
Foo.where{(bar.not_eq nil) & (bar.not_eq '') | (baz.not_eq nil) & (baz.not_eq nil)}
Here is the link for more info: http://erniemiller.org/projects/squeel/
There are a few different ways you can write that in squeel, it supports a few different syntax styles so if you don't liked the one above there are alternatives.
The sane way to deal with this (if you have the rights do do this of course on the database) is to disallow empty string values in the database. Then you can do Foo.where(:bar => nil). I use attribute_normalizer for this, and also to format values correctly.
https://github.com/mdeering/attribute_normalizer
A quick search also reveals nilify blanks, but I haven't tried that because attribute normalizer already provides that functionality for me.
https://github.com/rubiety/nilify_blanks
The resulting sql for the search you want if you have a well kept database (either null or empty string values for empty fields is probably as short as it gets. (I prefer empty strings myself).
using the linqtemplates, I tried getting the linq syntax close to what is in the docs
var query = from c in db.CountyLookups
join s in db.StateLookUps on
c.StateLookupID equals
s.StateLookupID
where c.Name2 == countyName &&
s.Abbr == stateAbbr
select new
{
Latitude = c.Latitude,
Longitude = c.Longitude
};
var result = query.SingleOrDefault();
but when .SingleOrDefault() is called, I get a yellow screen of darn that says:
System.NotSupportedException: The member 'StateLookupID' is not supported
the stack trace ends up at:
SubSonic.Linq.Structure.TSqlFormatter.VisitMemberAccess(MemberExpression m)
the StateLookupID column has underscores in the database and is a regular int pk/fk.
what am I doing wrong?
So apparently VisitMemberAccess has no idea what to do with an int, only string and datetime (starting on line 152 of SubSonic.Linq.Structure.TSqlFormatter). I don't know why this would be called on a join, since a join is usually between an int pk/fk (or guid if you like).
I ended up scrapping the linq query in favor of SubSonic.Query.Select. Here is my new code that works:
var query = db.Select.From<CountyLookup>()
.InnerJoin<StateLookUp>()
.Where(CountyLookupTable.Name2Column)
.IsEqualTo(countyName)
.And(StateLookUpTable.AbbrColumn)
.IsEqualTo(stateAbbr);
I then call ExecuteTypedList and map the results back to my model class. Works like buttah. Just wanted to use linq in this case.
I get this error when I've added properties to my models (the IsValid property as mentioned in ASP.Net MVC 1.0, thanks Rob).
I've had this problem on and off for a bit, and I think I've got it nailed down to the query builder trying to build a query for something that should be done in code, not TSQL.
When it tries to generate the SQL, it descends down the path to generate the TSQL via VisitMemberAccess on a complex type (maybe a another model) but it only knows how to perform operations on datetimes and strings in VisitMemberAccess. I'm sorry if this is a bit incoherent, but I'm trying to get my head around it.
To get around this consider using something like LinqKit AsExpandable prior to any operation which will do the TSQL generation. I've tried this on a simple OrderBy which was going BANG and it appears to work but i have no idea yet what it will do to performance.
Actually I take that back I overcame my problem problem by doing
Stuff.All().Where(x=>x.Someid == id).ToArray()
.AsQueryable()
.Where(x=>x.SomeProp.SomeFlag == true);
It is crud, but it works.
This still appears to be a problem; namely in simple cases such as:
var list = from lang in db.Languages
join site in db.SiteConfigLanguages on
lang.Code equals site.LanguageCode
select lang;
This should evaluate to simple SQL (although pointless in this example):
SELECT Language.* FROM Language LEFT JOIN SiteConfigLanguage ON Language.Code = SiteConfigLanguage.LanguageCode;
It fails inside the same VisitMemberAccess function as (in this case) Language is not a recognisable declaring type (i.e. String or DateTime). It is very similar to the description #matware provided above however it sounds as though the "IsValid" member is pure C# code whereas in this case lang.Code is simply a reference to a column in the database.
I'm currently investigating workarounds as this is only a portion of the larger LINQ query which is failing for me; if I find anything I will post it here. Otherwise, any other solutions/workarounds to this problem known?
UPDATE: Ignore me here; this is simply due to me missing a simple line on the LINQ statement; you need to make sure that you use the "into" keyword to complete things!
i.e.
var list = from lang in db.Languages
join site in db.SiteConfigLanguages on
lang.Code equals site.LanguageCode into sl
from siteLang in sl.DefaultIfEmpty()
select lang;
I've got another error mind you but at least this particular exception is solved. The next one looks a bit nastier unfortunately (inside System.Linq library).