setting a value based on another value in a linq query - c#

I'm changing a variable from a string a byte in my business logic but I'm not touching the database field that contains the value yet. So in the meantime, I'm looking for a c# equivalent to javascript's conditional syntax SomeValue = (TestValue === Something) ? 1 : 2;
Basically, the linq-to-sql query I have looks like this:
var TheOutput = from x in MyDC.SomeTable
....
select new SomeModel()
{
SomeByte = (x.SomeField === "test") ? 1 : 0
}
SomeField is a string and if it's equal to some test string then I want the property of the output's model to be set to a byte.

Use
(x.SomeField == "test") ? 1 : 0;

Cast to byte explicitly. SomeByte = (byte)(x.SomeField=="test"?1:0) should work.

for example
select new SomeModel()
{
SomeByte = (x.SomeField == "test") ? Convert.ToByte(1); : Convert.ToByte(0);
}

Related

C# 8: Linq Select, Parse String into Nullable Int

I am trying to Parse a String into Nullable int, with Linq select. The following last line is not working in Select. Receiving Error below. How can it be fixed?
Resource: https://stackoverflow.com/a/45066/13889515
var aviationInfo = _dbContext.Cpamlt
.Where(c=> c.Account == bppInfoRequestDto.AccountNumber)
.Select(cpamlt => new BppAviationInfoDto()
{
AccountNumberIdentityId = cpamlt.Cpamltid,
SerialNumber = cpamlt.Vinserno,
Manufacturer = cpamlt.Manmod,
MakeModel = cpamlt.Manmak,
YearManufactured = Int32.TryParse(cpamlt.Manyr, out tempVal) ? Int32.Parse(cpamlt.Manyr) : (int?)null,
Error: The name 'tempVal' does not exist in the current context
Trying to avoid Extension Methods if possible
Using Net Core 3.1 with C#8
The syntax requires you to define the variable, if you haven't previously. So use
Int32.TryParse(cpamlt.Manyr, out int tempVal)
But, your code can be shortened, as tempVal will contain the value you want, you don't need to parse again -
YearManufactured = Int32.TryParse(cpamlt.Manyr, out int tempVal) ? tempVal : (int?)null,
You can create a new method which should wrap this operation.
static int? NullableParse(string input)
{
int output = 0;
if (!int.TryParse(input, out output))
{
return null;
}
return output;
}

C#: What is this statement doing? dynObj.#switch == 1 ? true : false

I recently took over some code and came a across a statement that I wasn't sure what it was doing so I decided to post it.
currCarbon.CleanGeneration = (dynObj.#switch == 1 ? true : false);
Since 'dynObj' is a dynamic object holding a json value, is it checking if 'dynObj' contains a 'Switch' key / value?
Thanks for you help!
dynamic dynObj = GetValues();
if (dynObj != null) //json string from API
{
// Read the first record's carbon index
var prevCarbon = _dbContext.WatttimeApilog.OrderByDescending(c => c.CreatedDate).FirstOrDefault();
if (prevCarbon == null) //NO previous carbon value from database
{
//Plug in default values
currCarbon.Percentage = defaultPercent;
currCarbon.CleanGeneration = false;
currCarbon.Rating = defaultRating;
currCarbon.ValidUntil = DateTime.UtcNow;
insertFlag = true;
}
else
{
currCarbon.Percentage = dynObj.percent;
currCarbon.CleanGeneration = (dynObj.#switch == 1 ? true : false);
currCarbon.Rating = Convert.ToByte(dynObj.rating);
currCarbon.ValidUntil = dynObj.validUntil;
}
It's setting CleanGeneration to true or false based on whether or not #switch is equal to one via a ternary operator.
EDIT: The code isn't the most clean and can be shortened to just currCarbon.CleanGeneration = dynObj.#switch == 1;
Linked is docs on the ternary operator:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/conditional-operator

How to handle null values from SQLite DB with C#?

EDIT:
Thanks to everyone who replied! I appreciate all of your answers :)
So I have a class with the following constructor:
public Transaction(DataRow row)
{
LastName = row.Field<string>("LastName");
FirstName = row.Field<string>("FirstName");
MI = row.ItemArray[3].ToString()[0];
ContactNumber = row.ItemArray[4].ToString();
Hours = int.Parse(row.ItemArray[5].ToString());
CheckIn = (DateTime)row.ItemArray[6];
roomNumber = int.Parse(row.ItemArray[9].ToString());
//Paid = row.Field<int>("Paid");
//TotalBill = row.Field<int>("TotalBill");
}
Notice I have 2 of them commented out with /'s That's because if I don't they return null values even if I try ''row.Field([Whatever]).GetValueOrDefault()'', it still comes out null and my constructor returns null. I also have my DB set with default values so IDK what's wrong.
Anyone got a work around? :)
The DataRow class has a method that is called IsNull and that could receive the column name.
Just combine it with the conditional operator
Paid = row.IsNull("Paid") ? 0 : row.Field<int>("Paid");
the same is true for all other fields that could contain a null value.
Just check for null first and supply a default value:
public Transaction(DataRow row)
{
LastName = row.Field<string>("LastName");
FirstName = row.Field<string>("FirstName");
MI = row.ItemArray[3].ToString()[0];
ContactNumber = row.ItemArray[4].ToString();
Hours = int.Parse(row.ItemArray[5].ToString());
CheckIn = (DateTime)row.ItemArray[6];
roomNumber = int.Parse(row.ItemArray[9].ToString());
Paid = row.Field<int?>("Paid") ?? 0;
TotalBill = row.Field<int?>("TotalBill") ?? 0;
}
See the ?? Operator (C# Reference) page on MSDN for further information on the ?? operator.
You can simply use the Nullable type and GetValueOrDefault method or use null coalescing operator.
Paid = row.Field<int?>("Paid").GetValueOrDefault()
or
Paid = row.Field<int?>("Paid") ?? 0
In both cases Paid will have a value of 0, you can change if you want.
Create your own little function that does a simple check.
Along the lines of:
public integer GetNumber (object val)
{
if (IsNumeric (val))
{
return val;
} else
{
return 0;
}
}
I'm not fantastic with C#, but that should give you an idea. Sorry about formatting, I'm on a phone which doesn't help at all.

Use a numeric value in a linq dynamic query string

I am trying to make a dynamic linq query that will check for values based on a string.
First of all, here's the query:
objQry = from o in m_Db.OBJECTS.Where(whereConditions)
select o;
if(!objQry.Any())
{
return null;
}
The whereConditions variable is a string I build and pass as parameter to find out the values I need. Here's examples of valid string:
OBJ_NAME == \"Sword\" and OBJ_OWNER == \"Stan\"
This will return any item whose name is "Sword" and owner is "Stan;
OBJ_COLOR == \"Blue\" OR OBJ_COLOR == \"Red\"
This will return any item which color is either blue or red.
Up to there, I'm fine, but now I have a problem: I need to check a decimal field. So I've tried this string:
OBJ_NUMBER == 1
But the query returns null even if there are objects which OBJ_NUMBER value is 1. It's a decimal. How can I indicate the query that they need to check for a decimal value?
**** EDIT ****
I have tried to "modify" the value passed so that it looks like this:
"CARD_NUMBER == Convert.ToDecimal(1)"
And now I have a different kind of error telling me this:
LINQ to Entities does not recognize the method 'System.Decimal ToDecimal(Int32)' method, and this method cannot be translated into a store expression.
Any clues anyone? I'm still looking for a way to do this. Thanks!
EDIT 2
You can get an example of how my code is shaped by looking at this question.
Let's come back at this problem. I want to check decimal values. Let's say that OBJ_NUMBER is a decimal field.
Using Dynamic Linq, I tried to read the decimal field. Say that I want to get each object which number is 1.27. The whereConditions field would then be shaped like this:
OBJ_NUMBER == 1.27
But then I would get an Invalid real literal '1.27' error. I don't know why.
So I have tried Gert Arnold's solution and done this instead:
decimal bDecimal = decimal.Parce(valueToParse);
param = new ObjectParameter("cardNumber", typeof(decimal)) { Value = bDecimal };
valuesToUse.Add("CARD_NUMBER == #cardNumber");
listParams.Add(param);
But I ended up having 2 problems:
The first problem is that my whereConditions string is shaped this way:
CARD_NUMBER == #cardNumber
But I get the following error:
No property or field 'cardNumber' exists in type 'CARD'
Leading me to believe that it cannot make the link between the object parameter and the string used to do the query.
As you can see, I have a list of Params. This is because I cannot know for sure how many parameters the user will chose. So each time the user enters a new search field, I have to create a new ObjectParameter and store it in a list. Here's how I try to do the thing after:
ObjectParameter[] arrayParameters = listParams.ToArray();
// Convert the list to an array
And then, when I try to make the query:
cardQry = from c in mDb.CARD.Where(whereConditions, arrayParameters)
select c;
But to no avail.
RESULTS
Based on the answered question below, I have developped something "awful", yet functional.
First of all, I ignore every decimal fields because I could never reach them with dynamic linq. Instead, I do this:
var valuesToParse = keyValuePair.Value.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries);
// Here I parse the value and, if that's the case, the symbol.
decimal baseValue = decimal.Parse(valuesToParse[0]);
if (valuesToParse.Count() > 1)
{
string baseMethod = valuesToParse[1];
if (baseMethod == ">" || baseMethod == ">=")
{
if (baseMethod == ">=")
{
baseValue--;
}
// The list is actually like this: Dictionary<string, object> list = new Dictionary<string, object>();
list.Add("low", baseValue);
// I kind of activate a tag telling me that the user is looking for a higher value.
cardHigher = true;
}
else
{
if (baseMethod == "<=")
{
baseValue++;
}
list.Add("low", baseValue);
cardLower = true;
}
}
else
{
//lowParam = new ObjectParameter("dec", typeof(decimal)) { Value = baseValue };
list.Add("low", baseValue);
}
cardNumberActivated = true;
At the end, when I get the list of objects, I do this:
if (list.Count > 0)
{
(example)
if (cardNumberActivated)
{
if (cardHigher)
{
q = mDb.CARD.Where("CARD_NUMBER >= #0", list["low"]).ToList();
}
else if (cardLower)
{
q = mDb.CARD.Where("CARD_NUMBER <= #0", list["low"]).ToList();
}
else
{
q = mDb.CARD.Where("CARD_NUMBER == #0", list["low"]).ToList();
}
}
}
// Here we get the orinalData with the basic filters.
listToReturn.AddRange(cardQry);
if (q != null)
{
//listToReturn.AddRange(q);
for (int i = 0; i < listToReturn.Count; i++)
{
var priceList1 = listToReturn[i];
if (!q.Any(_item => _item.CARD_NUMBER == priceList1.CARD_NUMBER))
{
listToReturn.RemoveAt(i);
i--;
}
}
}
And it works. This is not an elegant way to make it work, but I can validate the fields the way I wanted, and for this, I am thankful at last.
You should not build a query string with inline predicate values. Use parameters in stead. Then will also be able to specify the type:
var whereConditions= "it.CARD_NUMBER = #cardNumber";
var param = new ObjectParameter("cardNumber", typeof(decimal)) { Value = 1 };
objQry = from o in m_Db.OBJECTS.Where(whereConditions, param);
Edit
I don't know what doesn't work in your code. Here's just a random piece of working code derived from one of my own projects:
var param1 = new ObjectParameter("dec", typeof(decimal)) { Value = 90000m };
var param2 = new ObjectParameter("int", typeof(int)) { Value = 90000 };
var q = ValueHolders.Where("it.DecimalValue >= #dec OR it.IntegerValue > #int",
param1, param2).ToList();
Note that param1, param2 could also be an array of ObjectParameter.

Handling null objects in object setters

I am trying to use a nice near object setter, but have null issues.
My code right now:
var Result = new RefundReplyObject
{
AuthorisationNumber = reply.refundResponse.transactionDetails.authorisationNumber,
ChargeValue = reply.refundResponse.transactionDetails.totalAmount.amount,
Message = reply.refundResponse.transactionDetails.message,
ReconciliationReference = reply.refundResponse.transactionDetails.reconciliationReference,
SettlementDate = reply.refundResponse.transactionDetails.settlementDate,
Status = TransactionStatusToLocalModel(reply.refundResponse.transactionDetails.status),
TransactionReference = reply.refundResponse.transactionDetails.transactionReference
};
BUT ... 'totalAmount' might be null. So, I get errors.
Is there a neat way to handle this, so that if 'totalAmount' is null, then set chargevalue to zero?
How about a ternary operator, that checks to see if total amount is null. If it isn't, then use it's amount, otherwise 0.
ChargeValue = (reply.refundResponse.transactionDetails.totalAmount != null) ? reply.refundResponse.transactionDetails.totalAmount.amount : 0,
You could do, for example:
ChargeValue = reply.refundResponse.transactionDetails.totalAmount != null ? reply.refundResponse.transactionDetails.totalAmount.amount : 0
ternary operator to the rescue!
ChargeValue = totalAmount ? totalAmount.amount : 0;
Something like this?
ChargeValue = (null == reply.refundResponse.transactionDetails.totalAmount)
? 0
: reply.refundResponse.transactionDetails.totalAmount.amount
You're not going to be able to do it on the setter side of things since the exception is occuring before you even get there. You can get what you're after (and clean up your code substantially in the process) by doing something like this:
var trans = reply.refundResponse.transactionDetails;
var Result = new RefundReplyObject
{
AuthorisationNumber = trans.authorisationNumber,
ChargeValue = trans.totalAmount == null ? 0 : trans.totalAmount.amount,
Message = trans.message,
ReconciliationReference = trans.reconciliationReference,
SettlementDate = trans.settlementDate,
Status = TransactionStatusToLocalModeltrans.status),
TransactionReference = trans.transactionReference
};

Categories

Resources