Can't create a condition for null values in an array? - entity-framework

I am using linq expression trees to build a query.
My array:
string[] { null, null }
condition I want to implement:
x == null ? null : x.ToLower()
My linq expression looks like this:
{Param_0 => value(System.String[]).Any(Param_1 => (Param_0.FirstName.ToLower() == IIF((Param_1 == null), null, Param_1.ToLower())))}
This is my first attempt and I can't seem to find the correct way to do it
Constant = Expression.Condition(Expression.Equal(Constant, Expression.Constant(null, typeof(string))), Expression.Constant(null, typeof(string)), Expression.Call(Constant, "ToLower", null));
The expected result is to be able to call .ToLower() on elements that are not null

It seems to me that you want an expression that represents a function call with input a string, and output a string.
Expression<Func<string, string>>
How about a Lambda expression?
Expression<Func<string, string>> myExpression = (x) => (x==null) ? null : x.ToLower();
This expression can be used in a Queryable Select statement, like below:
IQueryable<string> myItems = new List<sring>()
{
"Abc",
null,
"DEF",
null,
"gHI",
}
.AsQueryable();
IQueryable<string> myLowerCaseItems = myItems.Select(myExpression);
foreach (string item in myLowerCaseItems)
{
if (item == null)
Console.WriteLine("<null>");
else
Console.WriteLine(item);
}
This yields the following output:
abc
def
ghi

Related

EF Core dynamic filter on boolean column

I want to apply a filter on boolean column which I will get it from the frontend as a parameter. It may be true, false or both. I can use the if statement to run the query but I need to add other methods like Take, Skip, OrderBy etc., which I have removed it for brevity. Is there any way to build the dynamic expression for below condition
if(parameter == "true")
_db.Employees.Where(e => e.Status = true)
else if (parameter == "false")
_db.Employees.Where(e => e.Status = false)
else
_db.Employees.ToList() //Return both true and false
LINQ queries are already dynamic. Every LINQ operator returns a new IQueryable<> query. You can construct a query bit by bit based on various conditions this way, eg :
var query=db.Employees.AsQueryable();
if(status=="Active")
{
query=query.Where(e=>e.Active);
}
if(dateAscending)
{
query=query.OrderBy(e=>e.Date);
}
if(page==1)
{
query=query.Take(pageSize);
}
else
{
query=query.Skip(page*pageSize).Take(pageSize);
}
...
var employees=await query.ToListAsync();
The tricky part is handling NULLs. In SQL, NULL means there's no value and any comparison with NULL returns NULL itself, which is translated as false. If Status or Active are nullable, you can't return any rows with NULLs by comparing with false. You'll have to compare with null explicitly. EF Core translates that to IS NULL.
Using a switch expression you can combine the various Status checks with this:
query = (status) switch
{
"true" => query.Where(e=>e.Status),
"false" => query.Where(e=>!e.Status),
"both" => query.Where(e=> e.Status !=null)
_ => query.Where(e=>e.Status == null)
};
This expression assumes that an empty string is meant to match NULLs. both means retrieving TRUE and FALSE but not NULL.
If don't care about NULLs, this can be simplified to :
query = (status) switch
{
"true" => query.Where(e=>e.Status),
"false" => query.Where(e=>!e.Status),
_ => query
};

Only update not null fields to Mongodb from Pojo

I want to update only those fields in mongo document that have values in the POJO. How do I do this?
I have a User collection with the following document:
{
_id: ObjectId("someId"),
name: "Foo",
age: 20,
gender: "male"
}
Now I want to update only the age to 22 so, I have a User pojo with age = 22 and _id = ObjectId("someId").
I don't want to use Updates.set("age",22) because then I'll have to handle every field. The field to be populated may be something other than age.
So, I used reflection to make a generic method to get the list of Update.sets for the pojo
classMembers = User::class.memberProperties
// get hashmap from pojo
val fieldsMap: HashMap<String, Any> =
mapper.convertValue(pojo, object : TypeReference<HashMap<String, Any>>() {}) ?:
throw CustomException( HttpStatus.BAD_REQUEST, "Could not parse request" )
// get hashmap from default/empty pojo
val defaultMap: HashMap<String, Any> =
mapper.convertValue(emptyPojo, object : TypeReference<HashMap<String, Any>>() {}) ?:
throw CustomException( HttpStatus.BAD_REQUEST, "Could not parse request" )
for (member in classMembers) {
val name = member.name
val value = fieldsMap[name]
//add to list only if the current value is not null or default and current value is different
if (value != null && defaultMap[member.name] != value && member.getter.annotations.isNotEmpty()) {
val field = (member.getter.annotations[0] as BsonProperty).value
setList.add(Updates.set(field, value))
}
}
This works. But I wanted to know if theres a better way to do it? A default way to do this via mongoClient or mongoTemplate or mongoRepository?

Skip inserting data in the list

I've got getter which gets list of my FilterModelRow. If condition is null I want to skip inserting the data into the list and the best do it inline
get getFilterRows {
return [FilterRowModel(Icon(Icons.title), 'Age', 'equal', age),
FilterRowModel(Icon(Icons.title), 'Age', 'min', minAge),
FilterRowModel(Icon(Icons.title), 'Age', 'max', maxAge)
];
}
I tried
...
age != null FilterRowModel(Icon(Icons.title), 'Age', 'equal', age): null
...
But that insert null which ends with an error. So how to completely skip adding line into the list if condition is met
Simplified version
var age = null;
List<int> myList = [age!=null ? age : null];
print(myList); //--> return [null] and I want to return empty list []
If you tell to your list to insert a null value, it will.
Now you have two options :
1 - You can instantiate your list and add values that are not null
List<int> myList = [];
if (age != null) myList.add(age);
2 - You can remove null values from your list with removeWhere method
myList.removeWhere((value) => value == null);

Drools Accumulate on Properties

I have inherited some Drools code and am trying to understand exactly how it is working.
The code in question should go through a number of dates from two different sources, and for one source find the earliest and the other source find the latest.
The code is:
when
$flags: Properties()
// these properties contain key/value pairs with dates (as Strings)
$root: Map()
Map.Entry( key == "someRequest", $someRequestValue : value) from $root.entrySet()
$someRequestMap: Map() from $someRequestValue
// this map contains some timestamps as Strings
$earliestTimestamp: String() from accumulate(
$value : String(),
init( String found = null; ),
action( found = found == null? $value : ($value.compareTo(found) < 0? $value: found); ),
result( found )
)
$latestTimestamp: String() from accumulate(
$value : String(),
init( String found = null; ),
action( found = found == null? $value : ($value.compareTo(found) > 0? $value: found); ),
result( found )
)
then
log("earliestTimestamp: {}", $earliestTimestamp);
String latestDate = (String) $flags.get($latestTimestamp);
log("latestDate: {}", latestDate);
end
The $flags Properties are populated as so:
when
$flags: Properties()
$root: Map()
Map.Entry( key == "someRequest", $someRequestValue : value) from $root.entrySet()
$someRequestMap: Map() from $someRequestValue
Map.Entry( key == "timestamp", $timestampValue: value) from $someRequestMap.entrySet()
Map.Entry( key == "data", $dataValue: value) from $someRequestMap.entrySet()
$data: Map() from $dataValue
Map.Entry( key == "simple", $simpleValue: value) from $data.entrySet()
$simple: Map() from $simpleValue
Map.Entry( key == "somedate", $somedateValue: value) from $simple.entrySet()
then
$someRequestMap.remove("data");
update($root);
$flags.put($timestampValue, $somedateValue);
insert ($timestampValue);
end
And the JSON which is input to the rules is as so (with the timestamp strings):
{
"someRequest": {
"data": {
"simple": {
"somedate": "13-01-2016",
}
},
"timestamp": "2016-01-01 12:34:56.789"
}
}
I can see that it gets all the String facts available in working memory to get earliestTimestamp.
I think that for latestTimestamp, since it is called in the RHS on $flags.get, it is actually finding all Strings in $flags.
However if I insert log outputs inside the two accumulate action sections, all I see is the timestamp strings from working memory (I don't see the $flags strings).
I am comfortable enough using Drools but this bit of code has confused me in terms of how it works with the Properties.
Any info appreciated, thanks.

Filter condition not working properly on list (C#3.0)

I have a datatable that has many NULL or " " strings. Next I am type casting the DataTable to a list .
Now if I want to filter those conditions on this list and get the resultant value(without NULL or String.Empty or " " records) what should I do?
My code
DataTableExtensions.AsEnumerable(dt).ToList().ForEach(i =>
{
if (i[0] != null)
{
if ((i[0].ToString() != string.Empty)|| (i[0].ToString() != " "))
{
list = dt.AsEnumerable().ToList();
}
}
});
But I am getting all the records. It is not getting filtered.
Using C#3.0
Please help
Thanks
You're looking at i[0] so I'm going to assume that you're only interested in the first column of your table:
var rows = dt.AsEnumerable()
.Where(r => !r.IsNull(0) // check for DBNull
&& r[0] != null
&& r[0].ToString().Trim().Length > 0)
.ToList();
So that looks at every row but only returns the rows where the first column has a value and the string value is not empty or whitespace.