Linq where clause with nullable parameters - entity-framework

I'm trying to do a linq query which might have nullable params.
This is my linq call
listOfControlsVM = db.Controls.Where((status == null || s.Status.Description == status) && (impact == null || s.Impact == impact)).ToList();
Now either status or impact can be nullable params (I have two more but I removed them from the example). With the approach I have the query doesn't return the correct set of results.
I want to know if there is other better approach to work with nullable params in linq. For example if status or impact have value include them in the conditions, otherwise skip them.

There is a HasValue to check null value on nullable variable instead of null.
listOfControlsVM = db.Controls.Where((!status.HasValue || s.Status.Description == status) && (!impact.HasValue || s.Impact == impact)).ToList();
I hope this will help you out :)

Related

flutter null safety from prefs.setStringList -> error : the argument list<String?> can't be assigned to the parameter type List <String>

Hello I try to make null safety migration, but have a probleme with
prefs.setStringList("save_list_autre2",save_list.toList());
the error is : the argument list<String?> can't be assigned to the parameter type List
RegExp regExp = new RegExp(r'(...)');
var save_list= regExp.allMatches(decrypted).map((z) => z.group(0));
if(regExp.allMatches(decrypted)==null ){
[...]
} else {
prefs.setStringList("save_list_autre2",save_list.toList());
}
I add .toString() from save_list= regExp.allMatches(decrypted).map((z) => z.group(0).toString());
the error is removed but I don't know if it's the good solution
When you call z.group(0) the group method could return null if there was no group with the given index (0 in this case). so dart thinks you might have some null values on your list of strings.
The reality is that you shouldn't get any null values because you are passing a 0. So to tell dart that the method isn't returning null, use the ! operator:
regExp.allMatches(decrypted)
.map((z) => z.group(0)!)
If, by some chance, you happened to have any null values, this code will not work (as I said, I believe you won't but what do I know? I've never used regexes with dart)
If that's the case, you first need to filter the null values and then use the !:
regExp.allMatches(decrypted)
.map((z) => z.group(0))
.where((v) => v != null) // filter out null values
.map((v) => v!); // let dart know you don't have any null values.
Hopefully that's enough to fix the problem

How to fix FirstOrDefault returning Null in Linq

My Linq Query keeps returning the null error on FirstOrDefault
The cast to value type 'System.Int32' failed because the materialized value is null
because it can't find any records to match on the ClinicalAssetID form the ClinicalReading Table, fair enough!
But I want the fields in my details page just to appear blank if the table does not have matching entry.
But how can I handle the null issue when using the order by function ?
Current Code:
var ClinicalASSPATINCVM = (from s in db.ClinicalAssets
join cp in db.ClinicalPATs on s.ClinicalAssetID equals cp.ClinicalAssetID into AP
from subASSPAT in AP.DefaultIfEmpty()
join ci in db.ClinicalINSs on s.ClinicalAssetID equals ci.ClinicalAssetID into AI
from subASSINC in AI.DefaultIfEmpty()
join co in db.ClinicalReadings on s.ClinicalAssetID equals co.ClinicalAssetID into AR
let subASSRED = AR.OrderByDescending(subASSRED => subASSRED.MeterReadingDone).FirstOrDefault()
select new ClinicalASSPATINCVM
{
ClinicalAssetID = s.ClinicalAssetID,
AssetTypeName = s.AssetTypeName,
ProductName = s.ProductName,
ModelName = s.ModelName,
SupplierName = s.SupplierName,
ManufacturerName = s.ManufacturerName,
SerialNo = s.SerialNo,
PurchaseDate = s.PurchaseDate,
PoNo = s.PoNo,
Costing = s.Costing,
TeamName = s.TeamName,
StaffName = s.StaffName,
WarrantyEndDate = subASSPAT.WarrantyEndDate,
InspectionDate = subASSPAT.InspectionDate,
InspectionOutcomeResult = subASSPAT.InspectionOutcomeResult,
InspectionDocumnets = subASSPAT.InspectionDocumnets,
LastTypeofInspection = subASSINC.LastTypeofInspection,
NextInspectionDate = subASSINC.NextInspectionDate,
NextInspectionType = subASSINC.NextInspectionType,
MeterReadingDone = subASSRED.MeterReadingDone,
MeterReadingDue = subASSRED.MeterReadingDue,
MeterReading = subASSRED.MeterReading,
MeterUnitsUsed = subASSRED.MeterUnitsUsed,
FilterReplaced = subASSRED.FilterReplaced
}).FirstOrDefault(x => x.ClinicalAssetID == id);
Tried this but doesn't work
.DefaultIfEmpty(new ClinicalASSPATINCVM())
.FirstOrDefault()
Error was:
CS1929 'IOrderedEnumerable<ClinicalReading>' does not contain a definition for 'DefaultIfEmpty' and the best extension method overload 'Queryable.DefaultIfEmpty<ClinicalASSPATINCVM>(IQueryable<ClinicalASSPATINCVM>, ClinicalASSPATINCVM)' requires a receiver of type 'IQueryable<ClinicalASSPATINCVM>'
Feel a little closer with this but still errors
let subASSRED = AR.OrderByDescending(subASSRED => (subASSRED.MeterReadingDone != null) ? subASSRED.MeterReadingDone : String.Empty).FirstOrDefault()
Error:
CS0173 Type of conditional expression cannot be determined because there is no implicit conversion between 'System.DateTime?' and 'string'
The original error means that some of the following properties of the ClinicalASSPATINCVM class - MeterReadingDone, MeterReadingDue, MeterReading, MeterUnitsUsed, or FilterReplaced is of type int.
Remember that subASSRED here
let subASSRED = AR.OrderByDescending(subASSRED => subASSRED.MeterReadingDone).FirstOrDefault()
might be null (no corresponding record).
Now look at this part of the projection:
MeterReadingDone = subASSRED.MeterReadingDone,
MeterReadingDue = subASSRED.MeterReadingDue,
MeterReading = subASSRED.MeterReading,
MeterUnitsUsed = subASSRED.MeterUnitsUsed,
FilterReplaced = subASSRED.FilterReplaced
If that was LINQ to Objects, all these would generate NRE (Null Reference Exception) at runtime. In LINQ to Entities this is converted and executed as SQL. SQL has no issues with expression like subASSRED.SomeProperty because SQL supports NULL naturally even if SomeProperty normally does not allow NULL. So the SQL query executes normally, but now EF must materialize the result into objects, and the C# object property is not nullable, hence the error in question.
To solve it, find the int property(es) and use the following pattern inside query:
SomeIntProperty = (int?)subASSRED.SomeIntProperty ?? 0 // or other meaningful default
or change receiving object property type to int? and leave the original query as is.
Do the same for any non nullable type property, e.g. DateTime, double, decimal, Guid etc.
You're problem is because your DefaultIfEmpty is executed AsQueryable. Perform it AsEnumerable and it will work:
// create the default element only once!
static readonly ClinicalAssPatInVcm defaultElement = new ClinicalAssPatInVcm ();
var result = <my big linq query>
.Where(x => x.ClinicalAssetID == id)
.AsEnumerable()
.DefaultIfEmpty(defaultElement)
.FirstOrDefault();
This won't lead to a performance penalty!
Database management systems are extremely optimized for selecting data. One of the slower parts of a database query is the transport of the selected data to your local process. Hence it is wise to let the DBMS do most of the selecting, and only after you know that you only have the data that you really plan to use, move the data to your local process.
In your case, you need at utmost one element from your DBMS, and if there is nothing, you want to use a default object instead.
AsQueryable will move the selected data to your local process in a smart way, probably per "page" of selected data.
The page size is a good compromise: not too small, so you don't have to ask for the next page too often; not too large, so that you don't transfer much more items than you actually use.
Besides, because of the Where statement you expect at utmost one element anyway. So that a full "page" is fetched is no problem, the page will contain only one element.
After the page is fetched, DefaultIfEmpty checks if the page is empty, and if so, returns a sequence containing the defaultElement. If not, it returns the complete page.
After the DefaultIfEmpty you only take the first element, which is what you want.

LINQ to SQL compare nullable in subquery

I fail to translate a sql query to a linq query that could calculate some stock.
This is my test query that I'm trying to convert to a linq query.
SELECT
i.*,
(SELECT COUNT(t.*) FROM tickets t
WHERE t.starttime::time = i.sessionstarttime::time
AND t.starttime::date = '2018-04-06'::date)
as stock
FROM items I
-- note that the hardcoded date ('2018-04-06') is a function parameter
( tl;dr; how would you convert this PostgreSQL query to LINQ? )
My attempts so far are the variations of the following query:
var items = await _context.Items.Select(x => new Item
{
Id = x.Id,
IsTicket = x.IsTicket,
Name = x.Name,
Price = x.Price,
SaleItems = x.SaleItems,
SessionStartTime = x.SessionStartTime,
DateCreated = x.DateCreated,
DateEdit = x.DateEdit,
UserIdCreated = x.UserIdCreated,
UserIdEdited = x.UserIdEdited,
// calculate stock in subquery
Stock = _context.Tickets.Count(
t => t.StartTime.Date == ticketDate
&& x.SessionStartTime.HasValue
&& t.StartTime.Hour == x.SessionStartTime.Value.Hours // this is the part that is failing
&& t.State != TicketState.Canceled)
}).ToListAsync();
t.StartTime is Datetime and x.SessionStartTime is Nullable Timespan
So when I comment the line && t.StartTime.Hour == x.SessionStartTime.Value.Hours everything is fine, but with it I get warnings that it could not be translated and will be evaluated locally. But I don't want to download the whole ticket table just to count them.
The t.StartTime.Hour part is fine, I tried to perform static comparisons with both parameters. t.StartTime.Hour == 5 was translated without any problems, but x.SessionStartTime.Value.Hours == 5 failed to translate.
Also the problematic part in the application output:
([t].StartTime.Hour == Convert([x].SessionStartTime, TimeSpan).Hours))
So I guess that convert part is failing.
So what I'm missing and how I could work around this problem. Any help will be appreciated.
Update:
After experimenting a bit I have found two workarounds, that I wouldn't call the answers.
First I noticed that EF is trying to convert Nullable<TimeSpan> to a regular TimeSpan from the mentioned output: ([t].StartTime.Hour == Convert([x].SessionStartTime, TimeSpan).Hours))
I thought I could prevent that conversion by converting to a string and comparing the strings (I have a feeling this will bite me in the future):
t.StartTime.ToString().Contains(x.SessionStartTime.ToString())
The second workaround is only viable for my scenario since I know the items query is final and I can materialise it without calculated Stock, and then loop through the results and calculate it on a separate query. But this seems to add additional calls to the database and sacrifice some performance.
foreach(var x in items.Where(x=>x.SessionStartTime.HasValue))
{
// accessing the t.StartTime.TimeOfDay property seems to fail the LINQ to SQL as well
var hours = x.SessionStartTime.Value.Hours;
var minutes = x.SessionStartTime.Value.Minutes;
x.Stock = _context.Tickets.Count(t => t.StartTime.Date == ticketDate
&& t.StartTime.Hour == hours
&& t.StartTime.Minute == minutes);
}

How to use IN Operator inside Where Condition in Linq

I need a help to how to use IN Operator in linq ,
Here is my Code:
achieved =grouped.Key.SMCode=="HETAL1"?
grouped.AsEnumerable().Where(x => (x.SalesManCode=="HETAL1"||x.SalesManCode=="BAIJU") &&
x.OrderType == "Sales Invoice" && x.IsFromService==true).Sum(m => m.OrderValue):0
Here i need the value for both Salesmancode baiju and hetal1 ,but now i got value only for hetal1
i dont know , how to use IN operator in linq
pls help me to get the values of both salesmancode
Please try as shown below.
achieved =(grouped.Key.SMCode=="HETAL1" || grouped.Key.SMCode=="BAIJU") ?
grouped.AsEnumerable().Where(x => (x.SalesManCode=="HETAL1"||x.SalesManCode=="BAIJU") &&
x.OrderType == "Sales Invoice" && x.IsFromService==true).Sum(m => m.OrderValue):0

How do I use the CoffeeScript existential operator to check some object properties for undefined?

I would like to use the CoffeeScript existential operator to check some object properties for undefined. However, I encountered a little problem.
Code like this:
console.log test if test?
Compiles to:
if (typeof test !== "undefined" && test !== null) console.log(test);
Which is the behavior I would like to see. However, when I try using it against object properties, like this:
console.log test.test if test.test?
I get something like that:
if (test.test != null) console.log(test.test);
Which desn't look like a check against undefined at all. The only way I could have achieved the same (1:1) behavior as using it for objects was by using a larger check:
console.log test.test if typeof test.test != "undefined" and test.test != null
The question is - am I doing something wrong? Or is the compiled code what is enough to check for existence of a property (a null check with type conversion)?
This is a common point of confusion with the existential operator: Sometimes
x?
compiles to
typeof test !== "undefined" && test !== null
and other times it just compiles to
x != null
The two are equivalent, because x != null will be false when x is either null or undefined. So x != null is a more compact way of expressing (x !== undefined && x !== null). The reason the typeof compilation occurs is that the compiler thinks x may not have been defined at all, in which case doing an equality test would trigger ReferenceError: x is not defined.
In your particular case, test.test may have the value undefined, but you can't get a ReferenceError by referring to an undefined property on an existing object, so the compiler opts for the shorter output.
This JavaScript:
a.foo != null
actually does check if the foo property of a is neither undefined nor null. Note that a.foo? is translated to JavaScript that uses != null rather than !== null. The conversions that != does means that both of these are true:
null == null
undefined == null
A plain a? becomes this JavaScript:
typeof a !== "undefined" && a !== null
because there are three conditions to check:
Is there an a in scope anywhere?
Does a have a value of undefined?
Does a have a value of null?
The first condition is important as just saying a != null will trigger a ReferenceError if there is no a in scope but saying typeof a === 'undefined' won't. The typeof check also takes care of the a === undefined condition in 2. Then we can finish it off with a strict a !== null test as that takes care of 3 without the performance penalty of an unnecessary != (note: != and == are slower than !== and === due to the implicit conversions).
A little reading on what != and !== do might be fruitful:
MDN: Comparison Operators
As far as your comment on the deleted answer is concerned, if(a.foo) is perfectly valid syntax if you complete the if statement:
if(a.foo)
do_interesting_things()
# or
do_interesting_things() if(a.foo)
However, if(a.foo) and if(a.foo?) differ in how they handle 0, false, and ''.
Wild guess; have you tried console.log test.test if test?.test??
Just tested it with coffee -p -e 'console.log test.test if test?.test?', which compiles to:
(function() {
if ((typeof test !== "undefined" && test !== null ? test.test : void
0) != null) {
console.log(test.test); }
}).call(this);