Check null in Entity framework - entity-framework

string password = Infoware.Students.FirstOrDefault(x=>x.AdmissionNo == AdmissionNo && x.AdmissionNo != null).Password;
Here students is a table where I have AdmissionNo and Password columns, Need to get password if admissionNo exists in the table. This expression is fetching Password for given AdmissionNo if the admissionNo is present in the records but if the entered admissionNo is not found in the records then it throwing NullReference Exception.
How can I check that given AdmissionNo is not a Valid AdmissionNO ??

You can simply check for null using an if statement"
if ( AdmissionNo != null )
{
//your code
}
You can also check ObjectContextOptions.UseCSharpNullComparisonBehavior Property which was introduced in EF 5.0

You can check it using Any:
.Any(a => a.AdmissionNo == null)
Or using if statement:
string user = Infoware.Students.FirstOrDefault(x=>x.AdmissionNo == AdmissionNo && x.AdmissionNo != null);
if(user != null)
{
password = user.Password;
}

You just need to put your tests the other way around (as they will shortcut):
string password = Infoware.Students.FirstOrDefault(x=> x.AdmissionNo != null
&& x.AdmissionNo == AdmissionNo ).Password;
And re-reading your question, you issue is when nothing is found...
So:
string password;
var result = Infoware.Students.FirstOrDefault(x=> x.AdmissionNo != null
&& x.AdmissionNo == AdmissionNo );
if (result != null) {
password = result.Password;
}

Related

Solidity method taking in bytes32 and hashing but values with previous hash don't match

Here's the code:
function playGame(bytes32 hashedMove) public returns (bool) {
require(
playerOne != address(0x0) && playerTwo != address(0x0),
"Game needs more players to join first"
);
require(
msg.sender == playerOne || msg.sender == playerTwo,
"You did not join the game as a player"
);
if (msg.sender == playerOne && hashedPlayerOneMove == "") {
hashedPlayerOneMove = hashedMove;
emit PlayerMadeMove(playerOne);
} else if (msg.sender == playerTwo && hashedPlayerTwoMove == "") {
hashedPlayerTwoMove = hashedMove;
emit PlayerMadeMove(playerTwo);
} else {
return false;
}
return true;
}
The above method takes in a hashedMove argument which I am using the following site to get: https://emn178.github.io/online-tools/keccak_256.html
I send a value of 2test2 hashed which is 0x0698472c4668bddd0c694601ca101551bd7b5cfe6dc780ab37bccfc99ad22e4c
Now another method takes in the constituents of the hash which are 2 and test2 to compare it with the stored hash:
function revealPlayerChoice(uint256 move, bytes32 password)
public
returns (uint256)
{
require(
hashedPlayerOneMove != bytes32(0x0) &&
hashedPlayerTwoMove != bytes32(0x0),
"The game is still running!"
);
bytes32 hashedAnswer = getSaltedHash(move, password);
console.logBytes32(hashedAnswer);
console.logBytes32(hashedPlayerOneMove);
if (msg.sender == playerOne && hashedAnswer == hashedPlayerOneMove) {
playerOneMove = move;
} else if (
msg.sender == playerTwo && hashedAnswer == hashedPlayerTwoMove
) {
playerTwoMove = move;
}
if (playerOneMove != 0 && playerTwoMove != 0) {
getGameOutcome();
}
}
I'm sending 2 as uint and 0x0000000000000000000000000000000000000000000000000000007465737432 (test2 in bytes) to the revealPlayerChoice method. However the values I'm getting from the console log are different. hashedAnswer is the hash I'm calculating in the method and hashedPlayerOneMove is the hash stored in playGame method.
for example, The console log outputs are
0x566d7dd4e9dc72e9beef887f2982703a0d0f9dd1b6505ee3ff5310c7383637bd
0x0698472c4668bddd0c694601ca101551bd7b5cfe6dc780ab37bccfc99ad22e4c
I would like to understand why the values are different? I'm using keccak256 to hash in solidity (pragma solidity ^0.8.0;) as well:
function getSaltedHash(uint answer, bytes32 salt) pure returns (bytes32) {
return keccak256(abi.encodePacked(answer, salt));
}
The key to your problem might be what abi.encodePacked(answer, salt) is returning.
When you pass the following arguments:
uint256 answer = 2
bytes32 salt = 0x0000000000000000000000000000000000000000000000000000007465737432
abi.encodePacked(answer, salt) returns:
0x00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000007465737432
And then, if you run the keccak256(bytes) with the previous value, it returns:
0x566d7dd4e9dc72e9beef887f2982703a0d0f9dd1b6505ee3ff5310c7383637bd

FATAL_ERROR|System.LimitException: Too many SOQL queries: 201

I am getting too many SOQL queries 201 error in apex class
I tried to check the no of queries within loop
Below is exact error -
11:48:43.9 (2785518121)|FATAL_ERROR|System.LimitException: Too many SOQL queries: 201
Class.GEN_CalculateActToWinScores.calcUserEligible: line 1343, column 1
Class.GEN_ActonFactsScoreUserEligibleBatch.execute: line 74, column 1
11:48:43.9 (2851114444)|CODE_UNIT_FINISHED|GEN_ActonFactsScoreUserEligibleBatch
11:48:43.9 (2852614277)|EXECUTION_FINISHED
Below is the code for method GEN_CalculateActToWinScores.calcUserEligible -
// Method for set user as ready for AoF
public static void calcUserEligible(List<User> usersList ){
List<Act_on_Facts__c> actOnFactDelete = new List<Act_on_Facts__c>();
Set<String> oppOpenStageNameSet = new Set<String>();
oppOpenStageNameSet.add(GEN_Constants.OPPORTUNITY_IDENTIFY);
oppOpenStageNameSet.add(GEN_Constants.OPPORTUNITY_QUALIFY);
oppOpenStageNameSet.add(GEN_Constants.OPPORTUNITY_PROPOSE);
oppOpenStageNameSet.add(GEN_Constants.OPPORTUNITY_NEGOTIATE);
Set<String> oppReadOnlyRecordTypeNameSet = new Set<String>();
oppReadOnlyRecordTypeNameSet.add(GEN_Constants.READONLY_SINGLE_ACCOUNT_OPP_RECORDTYPENAME);
oppReadOnlyRecordTypeNameSet.add(GEN_Constants.READONLY_WON_AND_DONE_OPP_RECORDTYPENAME);
oppReadOnlyRecordTypeNameSet.add(GEN_Constants.READONLY_CHILD_OPP_RECORDTYPENAME);
oppReadOnlyRecordTypeNameSet.add(GEN_Constants.READONLY_MULTI_ACCOUNT_OPP_RECORDTYPENAME);
if(usersList.size() > 0){
List<Id> idList = new List<Id>();
Integer countResult = 0;
List<User> newUserList = new List<User>();
Integer limitQuery; //10000 //2001
Integer limitResult; //2000
if(CSL_ActOnFactsLimits__c.getValues('QUERY_LIMIT') != null){
limitQuery = Integer.valueOf(CSL_ActOnFactsLimits__c.getValues('QUERY_LIMIT').Value__c);
}
if(CSL_ActOnFactsLimits__c.getValues('MAX_QUERY_RESULTS') != null){
limitResult = Integer.valueOf(CSL_ActOnFactsLimits__c.getValues('MAX_QUERY_RESULTS').Value__c);
}
Boolean eligible = true;
for (User userElement : usersList){
String logDetail = ' QUERY_LIMIT:limitQuery: '+limitQuery+' MAX_QUERY_RESULTS:limitResult: '+limitResult;
logDetail += ' userElement.id: '+userElement.id;
eligible = true;
CSH_ActOnFacts_UserEligible__c userEligible = null;
if(CSH_ActOnFacts_UserEligible__c.getValues(userElement.id) != null){
userEligible = CSH_ActOnFacts_UserEligible__c.getValues(userElement.id);
}
CSH_ActOnFacts_UserEligible__c profileEligible = null;
if(CSH_ActOnFacts_UserEligible__c.getValues(userElement.ProfileId) != null){
profileEligible = CSH_ActOnFacts_UserEligible__c.getValues(userElement.ProfileId);
}
List<Act_on_Facts__c> actonfacts = [select id from Act_on_Facts__c where Lookup_User__c = : userElement.id limit 1];
if(userElement.ManagerId == null){
userElement.Line_Manager_Optional__c = true;
userElement.Act_On_Facts_Manager_List__c = null;
}
if(userElement.Default_Macro_Segment__c == null){
userElement.Default_Macro_Segment__c = 'None';
}
if (userElement.IsActive == false){
eligible = false;
}else if(profileEligible != null || userEligible != null) {
eligible = false;
}else{
countResult = [select count() from Account WHERE OwnerId = :userElement.id LIMIT :limitQuery];
logDetail += ' Account.countResult: '+countResult;
if(countResult!=null && countResult > limitResult ){
eligible = false;
}
if(eligible){
if(oppOpenStageNameSet !=null && oppOpenStageNameSet.size()>0 && oppReadOnlyRecordTypeNameSet !=null && oppReadOnlyRecordTypeNameSet.size()>0){
countResult = [select count() from Opportunity WHERE OwnerId = :userElement.id AND StageName IN:oppOpenStageNameSet AND RecordType.DeveloperName NOT IN: oppReadOnlyRecordTypeNameSet LIMIT :limitQuery];
logDetail += ' Opportunity.countResult: '+countResult;
if(countResult!=null && countResult > limitResult ){
eligible = false;
}
}
}
}
if(!eligible){
userElement.Act_on_Facts_Eligible__c = false;
// remove user from Act on Facts
if(actonfacts != null && actonfacts.size()>0){
for(Act_on_Facts__c a : actonfacts){
actOnFactDelete.add(a);
}
}
}else{
userElement.Act_on_Facts_Eligible__c = true;
}
logDetail += ' userElement.Act_on_Facts_Eligible__c: '+userElement.Act_on_Facts_Eligible__c;
ApplicationLog.logEntry(ApplicationLog.SEVERITY_INFO, 'A2WBatch', 'GEN_ActonFactsScoreUserEligibleBatch:'+userElement.id+': ', logDetail);
newUserList.add(userElement);
}
try{
if(newUserList.size()>0){
update newUserList;
system.debug('HC Update- newUserList ' + newUserList);
}
if(actOnFactDelete.size()>0){
delete actOnFactDelete;
system.debug('HC Update- actOnFactDelete ' + actOnFactDelete);
}
}catch (Exception e){
system.debug('Error updating user ' + e);
}
}
}
Code for GEN_ActonFactsScoreUserEligibleBatch.execute-
global void execute(Database.BatchableContext BC, List<sObject> scope){
CSH_A2W_Settings__c a2wCS = CSH_A2W_Settings__c.getInstance();
if(scope != null){
List<User> userList = scope;
if(userList.size()>0){
if(CSL_ActOnFactsLimits__c.getValues('run_userTrigger') != null){
CSL_ActOnFactsLimits__c run_userTrigger = CSL_ActOnFactsLimits__c.getValues('run_userTrigger');
run_userTrigger.Value__c = 'false';
update run_userTrigger;
}
//GEN_CalculateActOnFactsScores.calcUserEligible(userList); //Commented as part of Decommission activity of AoF
if(a2wCS != null && a2wCS.Enabled_in_Batches__c == True){
GEN_CalculateActToWinScores.calcUserEligible(userList);
}
}
}
}
I am trying to analysis what will be the best possible ways to remove these errors or is there any alternate way to implement the same.
All these are queries in a loop:
for (User userElement : usersList){
...
List<Act_on_Facts__c> actonfacts = [select id from Act_on_Facts__c where Lookup_User__c = : userElement.id limit 1];
...
countResult = [select count() from Account WHERE OwnerId = :userElement.id LIMIT :limitQuery];
...
[select count() from Opportunity WHERE OwnerId = :userElement.id AND StageName IN:oppOpenStageNameSet AND RecordType.DeveloperName NOT IN: oppReadOnlyRecordTypeNameSet LIMIT :limitQuery];
As a very quick & dirty solution you can change the batch's size (how many records are passed to each execute). Default is 200.
Call your class with optional parameter Database.executeBatch(new GEN_ActonFactsScoreUserEligibleBatch(), 10); and see if it helps.
"Proper" fix would require some restructuring, taking queries out of the loop, maybe using some Maps where user's id is the key...
If these were custom objects a "pro" Apex developer would cheat, make these queries in one go, pulling user and related lists, something like
SELECT Id,
(SELECT Id FROM Accounts__r LIMIT 1),
(SELECT Id FROM Opportunities__r WHERE ... LIMIT 1),
(SELECT Id FROM Act_On_Facts__r)
FROM User
WHERE Id IN :scope
This won't work here because relation from Account to owner doesn't have a nice name ("Accounts" won't work). You should be still able to do it on the custom object (last subquery in my example, you can call it outside of the loop)
You might still be able to pull something like that off but it'd probably require looking at sharing-related tables... I'd say doable but if you have time to play with it. If you don't - change scope size and call it a day. Will execute bit longer but 1-liner fix is a win in my book.

Entity framework linq inner join return object if condition is true

public UserMaster Login(UserMaster userMaster, string otp)
{
return (from um in _context.UserMasters.Where(u => u.UserName == userMaster.UserName && u.Password == userMaster.Password && u.IsDisplay == true && u.IsActive == true)
join pin in _context.UserPins.Where(p => p.Pin == otp) on um.UserId equals pin.UserId
select new { um }).SingleOrDefault();
}
I am trying to return a object of User if the Condition are met, i.e if the user has correct pass and username as well as correct otp from a different table. I only need/require to return the User Master Obj.
Giving following error
public UserMaster Login(UserMaster userMaster, string otp)
{
return (from um in _context.UserMasters.Where(u => u.UserName == userMaster.UserName && u.Password == userMaster.Password && u.IsDisplay == true && u.IsActive == true)
join pin in _context.UserPins.Where(p => p.Pin == otp) on um.UserId equals pin.UserId
select um).FirstOrDefault();
}

EF is not saving changes

I really hope someone can help me. I have following controller-action:
public ActionResult Edit(EditViewModel vm)
{
Item item= db.Items.Find(vm.ItemId);
if (ModelState.IsValid)
{
//breakpoint 1 --> everything works fine, if its debugged step by step from here
//if item´s contact is null or different from viewmodel --> override it
if (item.Contact == null || item.Contact.ContactId != vm.ContactId)
item.Contact = db.Contacts.Find(vm.ContactId);
//if the viewmodel have a ContractUnit set and its different from item´s --> override the contractunit
//is the ContractUnit in viewmodel null set item´s null too
if (vm.ContractUnitId.HasValue && ((item.ContractUnit != null && item.ContractUnit.ContractUnitId != vm.ContractUnitId) || item.ContractUnit == null))
item.ContractUnit = db.ContractUnits.Find(vm.ContractUnitId);
else
if (!vm.ContractUnitId.HasValue)
item.ContractUnit = null;
//same as above just for Building
if (vm.BuildingId.HasValue && ((item.Building != null && item.Building.BuildingId != vm.BuildingId) || item.Building == null))
item.Building = db.Buildings.Find(vm.BuildingId);
else
if (!vm.BuildingId.HasValue)
item.Building = null;
//same as above just for EconomicUnit
if (vm.EconomicUnitId.HasValue && ((item.EconomicUnit != null && item.EconomicUnit.EconomicUnitId != vm.EconomicUnitId) || item.EconomicUnit == null))
item.EconomicUnit = db.EconomicUnits.Find(vm.EconomicUnitId);
else
if (!vm.EconomicUnitId.HasValue)
item.EconomicUnit = null;
//breakpoint 2 --> (no changes to item, if its the first breakpoint)
item= vm.GetItem(item); //override non relational data
db.Entry(item).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
...
}
Method GetItem from EditViewModel:
public Item GetItem(Item item)
{
item.DateReported = this.DateReported; //Datetime
item.Description = this.Description; //String
item.FirstDeadline = this.FirstDeadline; //Datetime
item.SecondDeadline = this.SecondDeadline; //Datetime
item.ThirdDeadline = this.ThirdDeadline; //Datetime
item.ReplacementDeadline = this.ReplacementDeadline; //Datetime
return item;
}
The Problem: EF is not saving the changes to item.Building, item.ContractUnit or item.EconomicUnit. But it does when i am debugging it step by step.
There is no error or exception thrown and the viewmodel and model is filled properly.
I really hope someone can help me to solve this...
I removed the relations from the item-model and now only save the ids in a "long?" attribute. Well, its now additional work to get the related data but at least it works.
Try calling
DBSet.Attach(entityToUpdate);
before
db.Entry(item).State = EntityState.Modified;
Maybe this helps.

LINQ to Entity: How to include a conditional where condition

I'm new to EntityFramework and came across a problem with an unsupported function used in the Query.
Therefore I hope the community might help to find a elegant way.
The query tries to find a user based on the username and/or the windows username.
[Flags]
public enum IdentifierType
{
Username = 1,
Windows = 2,
Any = Username | Windows,
}
The following code throws an NotSupportedException because the Enum.HasFlag is cannot be translated into a store expression.
public User GetUser(IdentifierType type, string identifier, bool loadRelations = false)
{
using (var context = contextFactory.Invoke())
{
var user = context.Users.FirstOrDefault(u => u.Username == identifier && type.HasFlag(IdentifierType.Username)
|| u.WindowsUsername == identifier && type.HasFlag(IdentifierType.Windows));
return user;
}
}
If I rewrite the query the old Fashion way, the Query works but the boolean logic is executed in the DB:
public User GetUser(IdentifierType type, string identifier, bool loadRelations = false)
{
using (var context = contextFactory.Invoke())
{
var user = context.Users.FirstOrDefault(u => u.Username == identifier && (type & IdentifierType.Username) == IdentifierType.Username
|| u.WindowsUsername == identifier && (type & IdentifierType.Windows) == IdentifierType.Windows);
return user;
}
}
WHERE ((Username = #username) AND (1 = (3 & (1)))) OR (WindowsUsername
= #windowsusername) AND (2 = (3 & (2))))
How can I force the framework to evaluate the boolean logic before it is sent to the DB, so the binary operation is not done at DB Level?
Any ideas much appreciated!
for example:
public User GetUser(IdentifierType type, string identifier, bool loadRelations = false)
{
using (var context = contextFactory.Invoke())
{
IdentifierType tw = type & IdentifierType.Windows;
IdentifierType tu = type & IdentifierType.Username;
var user = context.Users.FirstOrDefault(u => u.Username == identifier && tu == IdentifierType.Username
|| u.WindowsUsername == identifier && tw == IdentifierType.Windows);
return user;
}
}
But I hope and believe that the database server detect that 1 = (3 & (1)) is a constant
Here you go (I've converted my code to yours so may not be syntactically 100%) ...
public User GetUser(IdentifierType type, string identifier, bool loadRelations = false)
{
using (var context = contextFactory.Invoke())
{
var user = context.Users.FirstOrDefault(u => u.Username == ((type.HasFlag(IdentifierType.Username)) ? identifier : u.Username) &&
&& u.WindowsUsername == ((type.HasFlag(IdentifierType.Username)) ? identifier : u.WindowsUsername);
return user;
}
}
Sorry, I've realized that the question did not point out the effective problem. After reading more about that, I had to rewrite the question and finally got a great answer from Gert Arnold, see here.
The LINQKit provides powerful extensions like the PredicateBuilder to cover dynamic queries with OR conditions.