StackOverflow Exception when setting object variable - c#

I am trying to extract data from a sql table, write it to an object and in turn put that in a list.
I'm using VS2017, C# and MS-SQL 2008.
When I run the code it extracts the data from the SQL table; dumps it into some variables (I know this isn't the fastest, I just wanted to confirm I was getting them), I instantiate the object and try to set the first value, I then get the stack overflow on the set operation.
Why is it fine setting a variable and printing to screen, but not putting it into a variable?
Error;
System.StackOverflowException HResult=0x800703E9 Message=Exception
of type 'System.StackOverflowException' was thrown.
Class;
class Company
{
public String MDWRowNumber { get => MDWRowNumber; set => MDWRowNumber = value; } //errors here on set => MDWRowNumber = value
public String MDWIdNumber { get => MDWIdNumber; set => MDWIdNumber = value; }
public String MDWCompanyName { get => MDWCompanyName; set => MDWCompanyName = value; }
}
Main;
sql = "SELECT RowNo, Id, Name FROM Company;";
command = new SqlCommand(sql, connection);
reader = command.ExecuteReader();
while (reader.Read())
{
Console.WriteLine(reader.GetValue(0).ToString());
Console.WriteLine(reader.GetValue(1).ToString());
Console.WriteLine(reader.GetValue(2).ToString());
a = reader.GetValue(0).ToString();
b = reader.GetValue(1).ToString();
c = reader.GetValue(2).ToString();
Console.WriteLine(a + " | " + b + " | " + c); // writes correct values as expected
Company company = new Company();
company.MDWRowNumber = a; /////Errors here/////
company.MDWIdNumber = b;
company.MDWCompanyName = c;
//Company company = new Company()
// {
// MDWRowNumber = reader.GetValue(0).ToString(), ///// without all junk above errors here /////
// MDWIdNumber = reader.GetValue(1).ToString(),
// MDWCompanyName = reader.GetValue(2).ToString()
// };
CompanyList.Add(company);
}
Console.WriteLine(CompanyList.First().MDWCompanyName);
reader.Close();
command.Dispose();

Here's the problem:
public String MDWRowNumber { get => MDWRowNumber;
The property calls itself - hence the stack overflow.
Either use a private variable,
private string _MDWRowNumber;
public String MDWRowNumber { get => _MDWRowNumber; set => _MDWRowNumber = value; }
or an auto property
public String MDWRowNumber { get; set; }

In your class you have
public String MDWRowNumber { get => MDWRowNumber; set => MDWRowNumber = value; }
you dont need all that, it should just be
public String MDWRowNumber { get; set; }
by putting itself in the underlying variable you've confused it.

Related

how can i convert a null value from sql to datetime or string in C#?

I am trying to get some datetime values that are null in SQL to my C# application but i get some errors. One of the errors is:
'Unable to cast object of type 'System.DBNull' to type 'System.String'
Please, can someone tell me how to set a null DateTime value from SQL to my c# application?
I have already tried casting my C# variables to datetime value and string but both dont work. I've searched in stackoverflow but didn't found a solution for me.
I've also tried another solution but then i retrieved the date: '01/01/0001' as value instead of 'null'
public static List<Kamer> GetOpenstaandeBoekingen()
{
var result = new List<Kamer>();
using (var conn = new SqlConnection(ConnectionString))
{
conn.Open();
const string query = "select b.boekingid, k.naam, bk.incheckdatum, bk.uitcheckdatum, b.hotelid, b.aantal_gasten, bk.kamerid from boeking b join klant k on k.klantid = b.boekingid join boekingkamer bk on b.boekingid = bk.boekingid where bk.incheckdatum is null and bk.uitcheckdatum is null";
SqlCommand selectKamers = new SqlCommand(query, conn);
SqlDataReader reader = selectKamers.ExecuteReader();
while (reader.Read())
{
Kamer kamer = new Kamer((int)reader["boekingid"], (string)reader["naam"], (string)reader["incheckdatum"], (string)reader["uitcheckdatum"], (int)reader["hotelid"], (int)reader["aantal_gasten"], (int)reader["kamerid"]);
result.Add(kamer);
}
reader.Close();
}
return result;
}
And here is my class with the constructor:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FontysHotel
{
public class Kamer
{
// instantie variabelen
private int id;
private string naam;
private DateTime incheck_datum;
private DateTime uitcheck_datum;
private int hotel;
private int aantal_personen;
private int kamernr;
// properties
public int Id
{
get
{
return id;
}
set
{
id = value;
}
}
public string Naam
{
get
{
return naam;
}
set
{
naam = value;
}
}
public string Incheck_datum
{
get
{
return incheck_datum.ToShortDateString();
}
set
{
incheck_datum = Convert.ToDateTime(value);
}
}
public string Uitcheck_datum
{
get
{
return uitcheck_datum.ToShortDateString();
}
set
{
uitcheck_datum = Convert.ToDateTime(value);
}
}
public int Hotel
{
get
{
return hotel;
}
set
{
hotel = value;
}
}
public int Aantal_personen
{
get
{
return aantal_personen;
}
set
{
aantal_personen = value;
}
}
public int Kamernr
{
get
{
return kamernr;
}
set
{
kamernr = value;
}
}
public Kamer(int id, string naam, string incheck_datum, string uitcheck_datum, int hotel, int aantal_personen, int kamernr)
{
Id = id;
Naam = naam;
Incheck_datum = incheck_datum;
Uitcheck_datum = uitcheck_datum;
Hotel = hotel;
Aantal_personen = aantal_personen;
Kamernr = kamernr;
}
}
}
Uitcheckdatum and incheckdatum are the date values.
So i want, when i run the query is shows everything where are dates with null, it is for a hotel system and i want to show what bookings haven't checked in or out yet.
One way is to declare your DateTime variables as being a Nullable type, this is done by using the ? sign at the end such as this.
private DateTime? incheck_datum;
private DateTime? uitcheck_datum;
But it might be a better approach to look for, trap, and handle DB Nulls and then set default or min values like this
if (IsDBNullreader.IsDBNull(indexOfUitCheckDatum))
uitcheckdatum = DateTime.Minvalue;
else
uitcheckdatum = reader["uitcheckdatum"];
I would avoid direct initialization of an object without any previous check.
If you want to treat a DBNull value from the database as a null DateTime, there's no other option than declaring your two fields in the Kamer class using the nullable version DateTime? instead, since DateTime alone is a struct, a value type, which cannot be null. With that, you could do:
set
{
uitcheck_datum = string.IsNullOrEmpty(value) ? null : Convert.ToDateTime(value);
}
And in the loop:
while (reader.Read())
{
string incheckdatum = reader["incheckdatum"] as string;
string uitcheckdatum = reader["uitcheckdatum"] as string;
Kamer kamer = new Kamer((int)reader["boekingid"], (string)reader["naam"],
incheckdatum, uitcheckdatum, (int)reader["hotelid"],
(int)reader["aantal_gasten"], (int)reader["kamerid"]);
result.Add(kamer);
}
as saves you from possible casting exceptions. The indexer returns an instance of object. If it can't be cast to string, then null is returned.
In case you don't want to declare those fields as DateTime?, then just replace null in the set with a dummy date of your choice, e.g. DateTime.Now.
Also, make sure the string you receive from the database is a convertable string, or Convert will throw an exception. Maybe you'd want to add a try-catch to handle it.

Reading Data from database and storing the data in a List

I'm reading some data from a database (information on properties) and i store the information in Property objects. I put the objects in a list of type Property and i display the contents of the list in a listbox. However instead of getting different data for each object I'm getting the same data multiple times. Ps. I instantiate the Property object inside the while loop and the issue persists.
void fillListBoxWithProperties()
{
List<Property> propList = new List<Property>();
db_connection();
MySqlCommand cmd = new MySqlCommand();
cmd.CommandText = "select * from property ";
cmd.Connection = connect;
MySqlDataReader dr = cmd.ExecuteReader();
while(dr.Read())
{
Property prop = new Property();
prop.PropId = Convert.ToInt32(dr["propertyId"]);
prop.Address = dr["Address"].ToString();
prop.PropType = dr["PropertyType"].ToString();
propList.Add(prop);
}
foreach(Property details in propList)
{
lstBoxProperties.Items.Add(String.Format("{0} {1}", details.PropId, details.Address));
}
}
What the list box prints
If i add this code to the loop just for testing:
Property prop = new Property();
prop.PropId = Convert.ToInt32(dr["propertyId"]);
prop.Address = dr["Address"].ToString();
prop.PropType = dr["PropertyType"].ToString();
propList.Add(prop);
//added code
foreach (Property o in propList)
{
Console.WriteLine(o.toString());
}
The result in the console is the following:
Ballyare,
Rathmulan,
Rathmulan,
Letterkenny,
Letterkenny,
Letterkenny,
Convoy,
Convoy,
Convoy,
Convoy,
Gweedore,
Gweedore,
Gweedore,
Gweedore,
Gweedore,
Glenties,
Glenties,
Glenties,
Glenties,
Glenties,
Glenties,
Property Class Code:
class Property
{
private static int _propId =0;
private static string _address="";
private static string _propType="";
public Property()
{
}
public int PropId
{
get { return _propId; }
set { _propId = value; }
}
public string Address
{
get { return _address; }
set { _address = value; }
}
public string PropType
{
get { return _propType; }
set { _propType = value; }
}
}
Well, now after you added the Property class, it's quite clear why all of your instances seem to have the same content. You made your private members holding the data static. So they don't exist separately for each instance but only once for all instances of the class. Remove the static keyword (and see some introduction for what it does)

Return IQueryable<T> from another class instance

What I'm trying to accomplish is to make a base class that returns a general purpose IQueryable<T> and use that IQueryable from another class instance to filter further.
Es.
The base class return all records, and the calling class filters from there on.
This is the base class and getDealer_query is the method that returns the main IQueryable
public class Dealer
{
public DAL.DBConn_Nav db = null;
public G4.Elements.Identity oIdentity = null;
public Dealer()
{
oIdentity = new G4.Elements.Identity();
oIdentity.read();
}
public IQueryable<outerViewModel.NavisionDAL.vmDealer> getDealer_query()
{
IQueryable<vmDealer> dealer = (from d in db.DENTALICA_S_P_A__Customer
select new vmDealer()
{
idDealer = d.No_,
name = d.Name + (d.Name_2.Length > 0 ? " " + d.Name_2 : ""),
address = d.Address + (d.Address_2.Length > 0 ? " " + d.Address_2 : ""),
city = d.City,
zip = d.Post_Code,
county = d.County,
email = d.E_Mail,
phone = d.Phone_No_,
fax = d.Fax_No_,
vat = d.VAT_Registration_No_,
ssn = d.Fiscal_Code,
businessAreaCode = d.Business_Area_Code,
businessZoneCode = d.Business_Zone_Code,
clienteDiretto = (d.Cliente_Diretto == (byte)1 ? true : false),
aggancioOrdiniWeb = (d.Deposito_Agg__Ordini_Web == (byte)1 ? true : false),
aggancioOrdiniG4 = (d.Deposito_Agg__Ordini_G4 == (byte)1 ? true : false),
notUse = (d.Not_Use == (byte)1 ? true : false),
blocked = d.Blocked,
shipmentMethodCode = d.Shipment_Method_Code,
paymentTermsCode = d.Payment_Terms_Code,
paymentMethodCode = d.Payment_Method_Code,
shippingAgentCode = d.Shipping_Agent_Code,
customerPriceGroup = d.Customer_Price_Group,
customerDiscountGroup = d.Customer_Disc__Group,
identificaCliente = d.Identifica_Cliente
});
return dealer;
}
Here is the other Class Customer that calls the method from an instance of Dealer and finally Lists data.
public class Customer
{
G4.Elements.Identity oIdentity = null;
DAL.DBConn_Nav navDB = null;
public Customer()
{
//oIdentity = new G4.Elements.Identity();
//oIdentity.read();
}
///// <summary>
///// Recupera l'elenco dei clienti Navision (i Depositi pr G4) visibili ad un particolare utente
///// </summary>
///// <returns></returns>
public IQueryable<outerViewModel.NavisionDAL.vmDealer> getCustomerForOperator_query()
{
string idOperator = !string.IsNullOrEmpty(oIdentity.selectedId) ? oIdentity.selectedId : oIdentity.id;
using (navDB = new DAL.DBConn_Nav()) {
G4.Models.NavisionDAL.Dealer oD = new G4.Models.NavisionDAL.Dealer();
// Tutti i Clienti
IQueryable<outerViewModel.NavisionDAL.vmDealer> allCustomerList_query = oD.getDealer_query();
IQueryable<outerViewModel.NavisionDAL.vmDealer> customerForOperator_query = (from c in allCustomerList_query join cForOp in navDB.DENTALICA_S_P_A__SalesPerson_Customer on c.idDealer equals cForOp.Customer_No_
where cForOp.Salesperson_Code.Equals(idOperator)
&& cForOp.Starting_Date < DateTime.Now
&& (cForOp.Ending_Date.Equals(new DateTime(1753, 1, 1)) || cForOp.Ending_Date > DateTime.Now)
&& c.notUse.Equals(false)
select c).Distinct();
return customerForOperator_query;
}
}
public List<G4.outerViewModel.NavisionDAL.vmDealer> getCustomerForOperator()
{
using (navDB = new DAL.DBConn_Nav())
{
G4.Models.NavisionDAL.Dealer oD = new G4.Models.NavisionDAL.Dealer();
return getCustomerForOperator_query().ToList();
}
}
But it doesn't work! I get a generic "Object not set to an instance...".
Even if I try to debug I get nowhere cause the cursor doesn't stop.
To make it work I have to inherit the Dealer class from the Customer, but it is not what I want.
I think I'm missing something basic here.
Any Idea ?
EDIT - Simplified sample
I'm adding a simplified sample of the same code.
public class Dealer1
{
public DAL.DBConn_Nav db = null;
public Dealer1() {
}
public IQueryable<outerViewModel.NavisionDAL.vmDealer> getDealer_query()
{
IQueryable<vmDealer> dealer = (from d in db.DENTALICA_S_P_A__Customer
select new vmDealer()
{
idDealer = d.No_,
name = d.Name + (d.Name_2.Length > 0 ? " " + d.Name_2 : "")
});
return dealer;
}
}
public class Customer1
{
public DAL.DBConn_Nav db = null;
public Customer1()
{
}
public IQueryable<outerViewModel.NavisionDAL.vmDealer> getCustomerForOperator_query()
{
// All customers
G4.Models.NavisionDAL.Dealer1 oD = new G4.Models.NavisionDAL.Dealer1();
IQueryable<outerViewModel.NavisionDAL.vmDealer> allCustomerList_query = oD.getDealer_query().Where(i => i.name.StartsWith("AAA"));
return allCustomerList_query;
}
public List<G4.outerViewModel.NavisionDAL.vmDealer> getCustomerForOperator()
{
using (db = new DAL.DBConn_Nav())
{
return getCustomerForOperator_query().ToList();
}
}
}
There's nothing in your class Dealer that is setting the instance of db.
public DAL.DBConn_Nav db = null;
So even though in Customer you call using (navDB = new DAL.DBConn_Nav()) you are not passing navDB to Dealer so when you call getDealer_query() you get a null reference exception.
Based on your simplified sample I would recommend this code:
public class Dealer1
{
internal IQueryable<vmDealer> getDealer_query(DAL.DBConn_Nav db)
{
return
from d in db.DENTALICA_S_P_A__Customer
select new vmDealer()
{
idDealer = d.No_,
name = String.Join(" ", d.Name, d.Name_2)
};
}
}
public class Customer1
{
internal IQueryable<vmDealer> getCustomerForOperator_query(DAL.DBConn_Nav db)
{
return new Dealer1().getDealer_query(db).Where(i => i.name.StartsWith("AAA"));
}
public List<vmDealer> getCustomerForOperator()
{
using (var db = new DAL.DBConn_Nav())
{
return getCustomerForOperator_query(db).ToList();
}
}
}
This cleanly allows you to segregate responsibility, but it keeps you totally in control of the db instance - which you need to dispose of when done.
There shouldn't be a reason why allCustomerList_query is null.
To confirm that the linq statement in the getDealer_query method is working, I would change your code to look this:
List<outerViewModel.NavisionDAL.vmDealer> something = new List<outerViewModel.NavisionDAL.vmDealer>();
IQueryable<outerViewModel.NavisionDAL.vmDealer> test = something.AsQueryable();
return test;
In any case, to prevent the object ref error, you need to guarantee that an instance is returned, which, from the code example, I can't actually tell.
It's rather strange that you can't get a break point to stop inside the getDealer_query method. Are you running this in a test with multiple threads running? What could happen is that the other thread is having an unhandled exception raised, and thus the whole test stops. Try putting break points before return dealer in getDealer_query and on the line G4.Models.NavisionDAL.Dealer oD = new G4.Models.NavisionDAL.Dealer();. Assuming there are no other threads, the code has to stop on one of those.
Last note, looking at the code, I don't see where db is instantiated. If it isn't instantiated, you'll get an object ref error on this line:
`IQueryable<vmDealer> dealer = (from d in db.DENTALICA_S_P_A__Customer`

StackOverflow Exception from get and set

I have the following code:
namespace QuantStrats
{
class Program
{
static void Main(string[] args)
{
string FilePath = "C:\\Users\\files\\DJ.csv";
StreamReader streamReader = new StreamReader(FilePath);
string line;
List<Data> Data = new List<Data>();
while ((line = streamReader.ReadLine()) != null)
{
Data Tick = new Data();
string [] values = line.Split(',');
Tick.SetFields(values[1], values[2]);
Data.Add(Tick);
}
for (int ii = 0; ii < Data.Count; ii++)
{
Data TickDataValues = new Data();
TickDataValues = Data[ii];
Console.Write("TIME :" + TickDataValues.time + " Price : " + TickDataValues.price + Environment.NewLine);
}
Console.ReadLine();
}
}
class Data
{
public DateTime time
{
get { return this.time; }
set
{
this.time = value;
}
}
public double price
{
get { return this.price; }
set
{
this.price = value;
}
}
public void SetFields(string dateTimeValue, string PriceValue)
{
try
{
this.time = Convert.ToDateTime(dateTimeValue);
}
catch
{
Console.WriteLine("DateTimeFailed " + dateTimeValue + Environment.NewLine);
}
try
{
this.price = Convert.ToDouble(PriceValue);
}
catch
{
Console.WriteLine("PriceFailed " + PriceValue + Environment.NewLine);
}
}
}
}
But I get a stack overflow exception.
I know it is because I am not doing my get and sets correctly and am entering an infinite loop, but I cannot see why exactly this is happening?
public DateTime time
{
get { return this.time; }
set
{
this.time = value;
}
}
you aren't using backing fields, but setting the property itself from within the property setter.
You can fix this by using 1) an auto property
public DateTime Time { get; set; }
or 2) a backing field
private DateTime _time;
public Datetime Time
{
get { return _time; }
set { _time = value; }
}
they both equate to the same code.
For an explanation, when you get time in your code:
get { return this.time; }
it has to retrieve the value of time to return. It does that by calling the get on time, which has to get retrieve the value of time, etc.
I cannot see why exactly this is happening?
public double price
{
get { return this.price; }
set
{
this.price = value;
}
}
When you "get" price, the getter for price is called, which calls the getter for price, which calls the getter for price, which...
Just use auto-implement properties if you don't want to mess with a backing field:
public DateTime Time {get; set;}
public double Price {get; set;}
Some other observations:
The standard convention for property names is to start them with a capital letter, which is why I changed your properties to Time and Price in my examples.
You may want to consider using decimal for a property like Price if you do any floating-point math, since double has some slight imprecision when representing decimal numbers like 1.1. decimal will store the number exacly without any loss of precision.
Just writing to the console in a catch block seems incorrect. You are basically ignoring the error (from a logic flow sense). Rather than accepting strings in the class and parsing them, I would do the validation in the calling code and making sure the inputs are valid before passing them to the class.
Properties getters and setters are really just getXXX and setXXX methods (that's how they are compiled). Because you set the property from the property itself, it is if you were recurring endlessly on a method.
public DateTime time()
{
return time();
}
As stated by other answers, you can use backing fields or auto-implemented properties.

How to properly return a value from a PropertyMethod?

First of all, sorry (AGAIN) for my bad english.
Hello. I am still pretty new to C#.NET and we are now tasked by our professor to make a simple banking system using an ADO.NET database. My only problem now is that I can't seem to return the values from the PropertyMethod I created.
Here's how it works: I log in using my auto-generated username and password, in which in the next window, I would be able to deposit or withdraw. I wanted to display in my text boxes the retrieved information from the database.
Is there a proper way to return a value from the PropertyMethod? Or could I just employ other ways to properly retrieve the values I want? Thanks for all your answers.
Here is a part of my class library which authenticates login inputs and should return the values I want:
EDIT: I tried to look at the debugger to trace what's happening to the values, but they are returning nulls.
EDIT 2: Removed unnecessary codes.
EDIT 3: Thanks for noticing my errors. I have already fixed them. My program is working fine now.
here is the propery method
#region pm
public string FinalName
{
get { return finalName; }
set { finalName = value; }
}
public string FinalUname
{
get { return finalUname; }
set { finalUname = value; }
}
public string Acnum
{
get { return acnum; }
set { acnum = value; }
}
public string Pass
{
get { return pass; }
set { pass = value; }
}
public string Actype
{
get { return actype; }
set { actype = value; }
}
public string Mname
{
get { return mname; }
set { mname = value; }
}
public string Lname
{
get { return lname; }
set { lname = value; }
}
public string Fname
{
get { return fname; }
set { fname = value; }
}
decimal bal;
public decimal Bal
{
get { return bal; }
set { bal = value; }
}
public bool Dup
{
get { return dup; }
set { dup = value; }
}
#endregion
and here is the code for authenticating login.
public bool authenticateData(string uname, string pass)
{
bool found = false;
mySqlConnection.Open();
SqlCommand readData = new SqlCommand("AuthenticateLogin", mySqlConnection);
readData.CommandType = CommandType.StoredProcedure;
readData.Parameters.Add("#Username", SqlDbType.NVarChar).Value = uname;
readData.Parameters.Add("#Password", SqlDbType.NVarChar).Value = pass;
SqlDataReader dr;
dr = readData.ExecuteReader();
while (dr.Read())
{
found = true;
Actype = dr.GetString(3);
Bal = dr.GetDecimal(5);
Acnum = dr.GetString(6);
FinalName = dr.GetString(0) + " " + dr.GetString(2) + " " + dr.GetString(1);
break;
}
mySqlConnection.Close();
return found;
}
}
}
And here is my windows form:
private void Transact_Load(object sender, EventArgs e)
{
//here is where my bug occurs
txtName.Text = da.finalName;
txtUsername.Text = da.finalUname;
txtActType.Text = da.actype;
txtBal.Text = da.Bal.ToString();
type = txtActType.Text;
}
In your windows form you're accessing properties of an object called da ... but what is that? Are you actually setting da to a class of results anywhere? Your example code doesn't show this anywhere.
In authenticateData you use a datareader to populate some properties with your results, but those properties belong to what - the class that contains the authenticateData method? What is da, and how are you expecting it to have the values of your results?

Categories