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

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;
}

Related

c# updating table using LINQ to SQL?

I'm trying to update my table with this LINQ query
public void updateProduct(
int selectedIDToUpdate,
string prodNAMEToUp,
double prodPriceToUp,
string prodTYPEToUp,
int prodMANUToUp,
int prodCODEToUp)
{
DataClassesLINQEPOSDataContext dcld = new DataClassesLINQEPOSDataContext();
TBLPRODUCT tblprod = (from prod in dcld.TBLPRODUCTs
where prod.product_id == selectedIDToUpdate
select prod).First();
tblprod.product_name = prodNAMEToUp;
tblprod.product_price = prodPriceToUp;
tblprod.product_type = prodTYPEToUp;
tblprod.product_manufacturer = prodMANUToUp;
tblprod.product_code = prodCODEToUp;
dcld.SubmitChanges();
}
and then when I start to run the program I have this error
"InvalidCastException was unhandled"
"Specified cast is not valid."
Sorry I cant post image because I dont have enough reputation "points" :(
this is the control to pass the parameter on my class.
private void btnSaveToUpdate_Click(object sender, EventArgs e)
{
if (txtNameToUpdate.Text != "" ||
txtPriceToUpdate.Text != "" ||
txtTypeToUpdate.Text != "" ||
txtCodeToUpdate.Text != "")
{
Connection_Products update = new Connection_Products();
int selctedID = selectedIDToUpdate;
string prodNAMEToUp = txtNameToUpdate.Text;
double prodPriceToUp = double.Parse(txtPriceToUpdate.Text);
string prodTYPEToUp = txtTypeToUpdate.Text;
int prodMANUToUp = Convert.ToInt32(cmbManufacturerToUpdate.SelectedValue);
int prodCODEToUp = Convert.ToInt32(txtCodeToUpdate.Text);
update.updateProduct(selctedID, prodNAMEToUp, prodPriceToUp,
prodTYPEToUp, prodMANUToUp, prodCODEToUp);
}
else
{
MessageBox.Show("Error");
}
}
You most likely have some datatype mismatch between the values that you are trying to store and the data types of the columns in the database. This would be in one of the numeric columns.
If the prodPriceToUp column uses the money data type, this maps to a decimal type in Linq2Sql. You are trying to cast the double for the input parameter to decimal, which may be causing this issue. Try converting prodPriceToUp to a decimal before saving it.
I guess you are missing something in type mapping between updateProduct params and properties in tblprod. Please check here you are using correct types
This is because one of the following is trying to cast into an invalid type:
tblprod.product_name = prodNAMEToUp;
tblprod.product_price = prodPriceToUp;
tblprod.product_type = prodTYPEToUp;
tblprod.product_manufacturer = prodMANUToUp;
tblprod.product_code = prodCODEToUp;
Check for each of the these that the type of the left side is the same as the type of the right side. for example ensure that "tblprod.product_name" is a string property as you are trying to save a string to that property.
It is also possible that in your LINQ query, the where clause may have this problem, ensure that "prod.product_id" is an integer and not something else like a long or a short.
if these are all ok and you are still getting the exception then you will need to tell use what line is throwing the exception, and give use the details of the structure of tblprod;

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.

convertion issue with DateTime being null in a LINQ query

Here is the configuration of my datatables that I use in my linq query:
I have 2 dataset files (all the columns of all the tables have a DataType specified and their AllowDbNull property set to True):
* deposit_position_imbalance.xsd:
Contains 2 datables : - Imbalance
- ImbalanceDetailForRealTime
* dep_pos_imbalance_detail.xsd:
Contains 1 datatable : - Table
In the code below, the problem lies in the 2 lines "deal_date = b.deal_date".
Indeed, when I retrieve from the database b.deal_date that has a null value, it says in deposit_position_imbalance.Designer.cs :
"StrongTypingException was unhandled by user code"
"The value for column 'deal_date' in table 'ImbalanceDetailForRealTime' is DBNull."
"Specified cast is not valid".
Here is where it throws the error:
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public System.DateTime deal_date {
get {
try {
return ((global::System.DateTime)(this[this.tableImbalanceDetailForRealTime.deal_dateColumn]));
}
catch (global::System.InvalidCastException e) {
throw new global::System.Data.StrongTypingException("The value for column \'deal_date\' in table \'ImbalanceDetailForRealTime\' is DBNull." +
"", e);//ERROR THROWN HERE
}
}
set {
this[this.tableImbalanceDetailForRealTime.deal_dateColumn] = value;
}
}
I have tried to replace the line "deal_date = b.deal_date" by
"deal_date = (DateTime?)b.deal_date"
But I get 2 compilation errors: "The best overloaded method match for dep_pos_imbalance_detail.TableDataTable.AddTableRow(string, System.DateTime)' has some invalid arguments"
and "Argument '2': cannot convert from 'System.DateTime?' to 'System.DateTime'"
I have also tried to replace the line "deal_date = b.deal_date" by
"deal_date = b.deal_date == null ? (DateTime)DBNull.Value : b.deal_date"
But I get a compilation error: "Cannot convert type 'System.DBNull' to System.DateTime'"
I have then tried to replace the line "deal_date = b.deal_date" by
"deal_date = b.deal_date == null ? (DateTime?)DBNull.Value : b.deal_date"
But I get a compilation error: "Cannot convert type 'System.DBNull' to System.DateTime?'"
I have tried another thing : replacing "deal_date = b.deal_date" by
"deal_date = b.Isdeal_dateNull() ? default(DateTime?) : b.deal_date"
But again, I have the following errors:
"The best overloaded method match for dep_pos_imbalance_detail.TableDataTable.AddTableRow(string, System.DateTime)' has some invalid arguments"
and "Argument '2': cannot convert from 'System.DateTime?' to 'System.DateTime'"
The following image (sorry I am not yet allowed to insert an image in stackoverflow, so I put the link instead) shows the definition of my column deal_date in my dataset:
https://lh5.googleusercontent.com/-TEZZ9Hdnkl4/T1aRxF_i7II/AAAAAAAAAAg/BwzrVXIlOHE/s323/deal_date.jpg
We can see that I don't seem to have the possibility to set "System.DateTime?" but only "System.DateTime". And I don't want anything else than null as default value (do we have to put something else than the default value "" in order to make it work?)
UPDATE--> I've tried to put null instead of and the designer gives this error : "The string was not recognized as a valid DateTime. There is a unknown word starting at index 0.".
So I don't understand how I can manage to retrieve null values (I didn't put it in the code, but I have the same problem with the type double). I have the impression that my columns are set to enable null values but obviously not...
Also, when I try to modify the NullValue property to go from "(Throw Exception)" to "(Empty)" or "(Null)", the designer gives this error: "The value entered is not valid for the current data type."
Thank you for your help.
Here is my LINQ query:
deposit_position_imbalance.ImbalanceDataTable dtImbalanceForRealTime;
deposit_position_imbalance.ImbalanceDetailForRealTimeDataTable dtImbalanceDetailForRealTime;
dtImbalanceForRealTime = (deposit_position_imbalance.ImbalanceDataTable)(((deposit_position_imbalance)(dataManager.GetConfig(grid1).ParentDataSource)).Imbalance);
dtImbalanceDetailForRealTime = this.detailForRealTime;
// we separate security_id null and not null
// Security id is not null
deposit_position_imbalance.ImbalanceDataTable iWithSecurityIdNotNull = new deposit_position_imbalance.ImbalanceDataTable();
deposit_position_imbalance.ImbalanceRow[] dr1 = (deposit_position_imbalance.ImbalanceRow[])dtImbalanceForRealTime.Select("security_id is not null");
if (dr1.Count<deposit_position_imbalance.ImbalanceRow>() > 0)
{
DataTable looselyTypedDT1 = dr1.CopyToDataTable<deposit_position_imbalance.ImbalanceRow>();
iWithSecurityIdNotNull.Merge(looselyTypedDT1, true);
}
// Security id is null
deposit_position_imbalance.ImbalanceDataTable iWithSecurityIdNull = new deposit_position_imbalance.ImbalanceDataTable();
deposit_position_imbalance.ImbalanceRow[] dr2 = (deposit_position_imbalance.ImbalanceRow[])dtImbalanceForRealTime.Select("security_id is null");
if (dr2.Count<deposit_position_imbalance.ImbalanceRow>() > 0)
{
DataTable looselyTypedDT2 = dr2.CopyToDataTable<deposit_position_imbalance.ImbalanceRow>();
iWithSecurityIdNull.Merge(looselyTypedDT2, true);
}
var queryWithSecurityIdFound =
from a in iWithSecurityIdNotNull
join b in dtImbalanceDetailForRealTime
on new
{
a.situation_date,
a.security_id,
a.deposit_location_id,
a.account_keeper_id
}
equals new
{
b.situation_date,
b.security_id,
b.deposit_location_id,
b.account_keeper_id
}
where a.situation_date == situation_date
&& a.security_id == security_id
&& a.deposit_location_id == deposit_location_id
&& a.account_keeper_id == account_keeper_id
select new
{
name = a.bo_source_name,
deal_date = b.deal_date
};
var queryWithSecurityIdNotFound =
from a in iWithSecurityIdNull
join b in dtImbalanceDetailForRealTime
on new
{
a.situation_date,
a.security_code,
a.deposit_location_id,
a.account_keeper_id
}
equals new
{
b.situation_date,
b.security_code,
b.deposit_location_id,
b.account_keeper_id
}
where a.situation_date == situation_date
&& a.security_id == security_id
&& a.deposit_location_id == deposit_location_id
&& a.account_keeper_id == account_keeper_id
select new
{
name = a.bo_source_name,
deal_date = b.deal_date
};
var query_final = queryWithSecurityIdFound.Union(queryWithSecurityIdNotFound);
//We fill the 'dep_pos_imbalance_detail Table'
grid1.Clear();
foreach (var item in query_final)
{
((dep_pos_imbalance_detail.TableDataTable)grid1.DataSet.Tables["Table"]).AddTableRow(item.name, item.deal_date);
}
If this is a strongly typed DataSet, it autogenerates properties for nullable columns like Isdeal_dateNull which you should use instead.
if (!row.Isdeal_dateNull)
{
//do something
}
Efficient Coding With Strongly Typed DataSets
Checking for DBNull throws a StrongTypingException
I found a way to solve my issue. In my LINQ queries, I replace "deal_date = b.deal_date" by
"deal_date = b.Field('deal_date')". The convertion can then be made. I can then not use the Designer auto-generated method "AddTableRow" because it doesn't expect the right types. But I write this, a little bit longer but effective:
dep_pos_imbalance_detail.TableDataTable dt = ((dep_pos_imbalance_detail.TableDataTable)grid1.DataSet.Tables["Table"]);
dep_pos_imbalance_detail.TableRow dr = dt.NewTableRow();
foreach (var item in query_final)
{
dr = dt.NewTableRow();
dr.name = item.name;
if (item.deal_date.HasValue)
dr.deal_date = item.deal_date.Value;
else
dr.Setdeal_dateNull();
dt.AddTableRow(dr);
}

Convert a datetime to string

Howsit!
I encounter an error when i get a null value in my datareader.
public List<Complaint> View_all_complaints()
{
csDAL objdal= new csDAL();
List<Complaint> oblcomplist=new List<Complaint>();
using( IDataReader dr=objdal.executespreturndr("View_all_complaints"))
{
while (dr.Read())
{
Complaint objcomp= new Complaint();
populate_reader(dr,objcomp);
oblcomplist.Add(objcomp);
}
}
return oblcomplist;
}
public void populate_reader(IDataReader dr, Complaint objcomp)
{
objcomp.ref_num = dr.GetString(0);
objcomp.type = dr.GetString(1);
objcomp.desc = dr.GetString(2);
objcomp.date = dr.GetDateTime(3);
objcomp.housenum = dr.GetInt32(4);
objcomp.streetnum = dr.GetInt32(5);
objcomp.status = dr.GetString(6);
objcomp.priority = dr.GetString(7);
objcomp.cid = dr.GetInt32(8);
if (!dr.IsDBNull(9))
{
objcomp.resolved_date = dr.GetDateTime(9);
}
}
in sql resolved date allows null values, this is so because only when a complaint has been resolved , it must reflect that date otherwise it should be null.
if dr.getdatetime(9) is null then it must just set a string saying "Not Resolved"
please help!
You haven't shown what your Complaint type looks like, but basically you'll want to make sure that its resolved_date is of type DateTime? aka Nullable<DateTime>. That allows you to model a missing value elegantly.
As for displaying it - you haven't shown anything about where you display the data, but you'd want something like:
string text = complaint.ResolvedDate.HasValue ? complaint.ResolvedDate.ToString()
: "Not Resolved";
(I've changed this to use a property with the idiomatic name at the same time...)
IDataReader has a "IsDBNull" method, that should be called before calling GetXXX(), in case your value is not nullable.
For example:
objcomp.date = dr.GetDateTime(3);
should be:
objcomp.date = dr.IsDBNull(3) ? DateTime.MinValue : dr.GetDateTime(3);

Convert combobox string value to int

I have a question about converting types. I want to change the currently selected combobox value string to an int, but I get errors
My code:
int.Parse(age.SelectedItem.ToString());
What can I do for this problem?
Ok now we know the error, you can check for a null value before trying to parse it using:
if (comboBox1.SelectedItem != null)
{
int x = int.Parse(comboBox1.SelectedItem.ToString());
}
else { //Value is null }
You can avoid a null value being passed by setting the text property of the control to what ever default value you want.
If you are still not getting a value after making sure one is selected you really need to post your code.
TryParse is a good method for this sort of thing:
int value;
if (!Int32.TryParse(this.comboBoxNumeric.Text, out value))
{
//Do something fun...
}
Use a Convert.ToInt32 method. You can always use the databinding like this:
class A
{
public int ID{get;set;}
public string Name{get;set;}
}
cbo.DataSource = new A[]{new A{ID=1, Name="hello"}};
cbo.DisplayMember = "Name";
cbo.DisplayValue = "ID";
int id = Convert.ToInt32(cbo.SelectedValue);
A a = (A) cbo.SelectedItem;
int a_id = a.ID;
int a_name = a.Name;
If you use LINQ to DataSets, develop is very easy for C# program.
try
{
string name = comboBoxPort.SelectedItem.ToString();
int portBaudrate = Convert.ToInt32(comboBoxBaudrate.SelectedItem);
}
//just solved
//enjoy

Categories

Resources