C# access List after return - c#

I'm a noob with C# but I'm trying to create a simple code for connecting to my mysql database (most of the code I got from google). So I have this part where something from the database is selected and stored in a list. Now I want to access this from another class but I have no idea how to do that and I couldn't find the answer on google either (this thread also didn't worked for me: Access List from another class) so can anyone please help me?
Here's the particular code:
public List<string>[] Select()
{
string query = "SELECT * FROM users";
//Create a list to store the result
List<string>[] list = new List<string>[3];
list[0] = new List<string>();
list[1] = new List<string>();
list[2] = new List<string>();
//Open connection
if (this.OpenConnection() == true)
{
//Create Command
MySqlCommand cmd = new MySqlCommand(query, connection);
//Create a data reader and Execute the command
MySqlDataReader dataReader = cmd.ExecuteReader();
//Read the data and store them in the list
while (dataReader.Read())
{
list[0].Add(dataReader["id"] + "");
list[1].Add(dataReader["test"] + "");
list[2].Add(dataReader["balance"] + "");
}
//close Data Reader
dataReader.Close();
//close Connection
this.CloseConnection();
//return list to be displayed
return list;
}
else
{
return list;
}
}

Class containing your original method:
public class YourClass
{
public List<string>[] Select()
{
string query = "SELECT * FROM users";
//Create a list to store the result
List<string>[] list = new List<string>[3];
///
/// you original implementation here
///
}
}
Here Class where you use your method:
public class UsingClass
{
private YourClass _yourClass;
public UsingClass()
{
_yourClass = new YourClass();
}
private void SomeUsingMethod()
{
List<string>[] list = _yourClass.Select();
}
}

Seriously I think the way you've structured the data here, is strange.
You're creating an array of a objects, where the object is a List of string:
List<string>[] list = new List<string>[3];
You want to be thinking in objects; create a class that represents the data; in this case User. Something like this:
public class User
{
public string Id { get; set; }
public string Test { get; set; }
public string Balance { get; set; }
}
So personally I'd do the following:
Create a class that represents each user record.
Create a variable to hold a list of users.
Read from MySql and assign each record to a new User object.
Add the user to the list.
Return the list.
Change the return type of your Select method to be List<User> like this:
public List<User> Select() {
Then amend the rest of the method to create and return list of users.
public List<User> Select() {
List<User> list = new List<User>();
if (this.OpenConnection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataReader dataReader = cmd.ExecuteReader();
while (dataReader.Read())
{
User user = new User();
user.Id = dataReader["id"].toString();
user.Test = dataReader["test"].toString();
user.Balance = dataReader["balance"].toString();
list.Add(user);
}
dataReader.Close();
this.CloseConnection();
}
return list;
}
Then you can use your list something like this:
ClassThatContainsSelectMethod yourDBObject = new ClassThatContainsSelectMethod();
List<User> users = yourDBObject.Select();
foreach (User user in users)
{
Console.WriteLine(user.Id, user.Test, user.Balance);
}
This code of course could be better structured with factories and error/null checks but it should get you going in the right direction.

There are multiple ways to share data from classes.One of them is defining a property for the desired list and then accsess it. Lets say you have class data
class DataString
{
private string data = "data";
public string Data
{
get { return data}
set { data = value }
}
}
and
class Program
{
static void Main()
{
DataString dataStr = new DataString();
// Assigning the dataStr property causes the 'set' accessor to be called.
dataStr.Data = "some string";
// Evaluating the Hours property causes the 'get' accessor to be called.
System.Console.WriteLine(dataStr.Data); //this will display "some string"
}
}
You could the same way create a list class with your desired functions and variables and modiffy them with methods and access them with properties.

Related

ICollectionView with combobox

I have an ObservableCollection called States
in the States Model I have id, name, code, country
I would like to keep this collection with all of them but I would like to make a new collection to filter only the country. Currently I have this working by using this:
ViewModel.cs
StateCollectionView = CollectionViewSource.GetDefaultView(States);
StateCollectionView.Filter += StatesFilter;
public static void GetStates()
{
States.Clear();
using var conn = new SqlConnection(Settings.Default.ConnectionString);
conn.Open();
string qry = "SELECT * FROM dbo.State";
var cmd = new SqlCommand(qry, conn);
var reader = cmd.ExecuteReader();
while (reader.Read())
{
States.Add(new States(reader));
}
conn.Close();
}
public static bool StatesFilter(object state)
{
bool result = true;
if (state is States states)
{
if (states.Country)
{
Debug.Print(states.Name);
return true;
}
else
{
return false;
}
}
return result;
}
This is working by filtering the ObservableCollection of States but I would not like to filter that collection but rather create a ICollectionViewSource and use that in the binding in the view. As I need the States ObservableCollection to not be filtered to display correct data in other views.
I am trying to bind it to a ComboBox on the country drop down I want it to only show counties and the states dropdown to only show states. They are set apart by a bool value in the database.
EDIT: Sample
StateCollectionView = CollectionViewSource.GetDefaultView(States);
CountryCollectionView = CollectionViewSource.GetDefaultView(States);
StateCollectionView.Filter += StatesFilter;
CountryCollectionView.Filter += CountryFilter;
public static void GetStates()
{
States.Clear();
using var conn = new SqlConnection(Settings.Default.ConnectionString);
conn.Open();
string qry = "SELECT * FROM dbo.State";
var cmd = new SqlCommand(qry, conn);
var reader = cmd.ExecuteReader();
while (reader.Read())
{
States.Add(new States(reader));
}
conn.Close();
}
private static bool StatesFilter(object state) => state is States states && !states.Country;
private static bool CountryFilter(object state) => state is States states && states.Country;
public static ObservableCollection<States> States { get; set; } = new ObservableCollection<States>();
public static ICollectionView StateCollectionView { get; set; }
public static ICollectionView CountryCollectionView { get; set; }
You are not actually filtering the ObservableCollection<T> source collection but a view of it. But the thing is that WPF are always binding to this view instead of the actual source collection.
So instead of binding one control directly to the ObservableCollection<T> and another one to the filtered ICollectionView, you should create another (unfiltered) ICollectionView and bind to this one instead of the source collection. The other option would be to create two separate source collections and filter only one of them.
If you go with two ICollectionViews, you need to filter them separately using two different methods:
private static bool StatesFilter(object state) => state is States states && !states.Country;
private static bool CountryFilter(object state) => state is States states && states.Country;
Note that you need to create the views using the constructor instead of calling CollectionViewSource.GetDefaultView:
StateCollectionView = new ListCollectionView(States);
CountryCollectionView = new ListCollectionView(States);

Insert data in comboBox from database

I want to add all Id from customer table in combobox using class and this is my connection class connectionClass in which I made a function for selecting data from databse.
The second is my Customer form(this is customer form coding customerForm) in which i call a function which i made in connection class .
but it only showing the last id in customer form and i want all id in combobox
In the select() method you are returning a string,instead of that you need to populate
dataset and bind the data to combobox.
reader = sc.ExecuteReader();
DataTable dt = new DataTable();
dt.Columns.Add("customerid", typeof(string));
dt.Columns.Add("contactname", typeof(string));
dt.Load(reader);
regards
chandra
Instead of string return a List of strings as follows:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Fill_Combo();
}
public void Fill_Combo()
{
Connection2DB cst = new Connection2DB();
cmbBoxId.Items.AddRange(cst.Select().ToArray());
}
}
class Connection2DB
{
public List<string> Select()
{
var ids = new List<string>();
try
{
string sqlqry = "select ID from Customer";
SqlCommand cmds = new SqlCommand(sqlqry, _con);
SqlDataReader dr = cmds.ExecuteReader();
while (dr.Read())
{
ids.Add(dr["ID"].ToString());
}
}
catch (Exception ex)
{
// Handle exception here
}
return ids;
}
}
this function only returning only ID from Customer table. I want to multiple data from Customer table using same method. Can you help me in this one??
Normally, this is not how this site works. First, you should ask a specific question, and show what you have done. Then we may help you.
Here I will try to give you two general solutions for working with a database.
Solution 1:
Let`s say you want to display everything retrieved from the database to your windows form.
First, create the DataGridView object let's call it dataGridView1. You can create it using the designer as any other control. then use the codes below:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
dataGridView1.DataSource = GetData();
}
public DataTable GetData()
{
string ConStr = " your connection string "; // Write here your connection string
string query = #"SELECT * FROM Customer"; // or write your specific query
DataTable dataTable = new DataTable();
SqlConnection conn = new SqlConnection(ConStr);
SqlCommand cmd = new SqlCommand(query, conn);
SqlDataAdapter da = null;
try
{
conn.Open();
// create data adapter
da = new SqlDataAdapter(cmd);
// this will query your database and return the result to your datatable
da.Fill(dataTable);
}
catch (Exception ex)
{
MessageBox.Show($"Cannot read database: {ex.Message}");
}
finally
{
conn.Close();
if (da != null)
da.Dispose();
}
return dataTable;
}
public void FillDataGrid()
{
Connection2DB cst = new Connection2DB();
dataGridView1.DataSource = cst.GetData();
}
}
Solution 2:
Let's say from your database table you want to extract 3 columns: ID (INT), Name (VARCHAR(100)) and Value (VARCHAR(MAX).
First, create a class:
public class Customer
{
public int ID { get; set; }
public string Nmae { get; set; }
public string Value { get; set; }
}
Create the function which returns the list of Customers:
public List<Customer> GetCustomers()
{
var customers = new List<Customer>();
try
{
string sqlqry = "SELECT ID, Name, Value FROM Customer";
SqlCommand cmds = new SqlCommand(sqlqry, _con); // here _con is your predefined SqlConnection object
SqlDataReader dr = cmds.ExecuteReader();
while (dr.Read())
{
customers.Add(new Customer
{
ID = (int)dr["ID"],
Nmae = dr["Name"].ToString(),
Value = dr["Value"].ToString(),
});
}
}
catch (Exception ex)
{
// Handle exception here
}
return customers;
}
Then you can use this data as you want. For example, to fill your ComboBox with IDs you can use this:
public void Fill_Combo()
{
var customers = GetCustomers();
var ids = customers.Select(x => x.ID.ToString());
cmbBoxId.Items.AddRange(ids.ToArray());
}

C# - MySql - Best way to convert data from MySqlDataReader to different models

I have experience in working and fixing bugs with existing code bases that implement MySql code, but have to design a new program from scratch at my new job. I am not sure what is the best way to return data from MySqlDataReader to my custom models. Please advise!
Here's what I have,
Folder structure:
Models (folder)
Metadata.cs
User.cs
MySqlDb.cs
Metadata.cs: Reresents data from metadata table
public class Metadata
{
public int Id { get; set; }
public string Title { get; set; }
public string Sku { get; set; }
public bool IsLive { get; set; }
}
User.cs: Represents data from user table
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
public int Age { get; set; }
public string Address { get; set; }
}
MySqlDb.cs
using MySql.Data;
using MySql.Data.MySqlClient;
public class MySqlDb
{
public MySqlConnection Connection { get; set;}
public MySqlDb(string connectionString)
{
Connection = new MySqlConnection(connectionString);
}
public List<Metadata> RunSelectQueryForMetadata(string query)
{
var rdr = new MySqlCommand(query, Connection).ExecuteReader();
var metadata = new List<Metadata>();
using (rdr)
{
while(rdr.Read())
{
metadata.Add(
new Metadata {
Id = rdr["id"],
Title = rdr["title"],
Sku = rdr["sku"],
IsLive = rdr["islive"],
});
} // while
} // using
return metadata;
} // public void RunSelectQuery(string query)
} // public class MySqlDb
If I try to get Users data, I am thinking of writing another method (RunSelectQueryForUsers). I would like to avoid writing different methods for different tables. I am not sure how to use one method for retrieving data from different tables with different data structures and typecast them to the Model I want.
Any help is greatly appreciated!!
One way is to use micro-orm such as Dapper which is a simple object mapper built for .Net. Dapper extends the IDbConnection by providing useful extension methods to query your database.
Example of implementing dapper within your current menthod:
public List<Metadata> RunSelectQueryForMetadata(string query)
{
var metadata = new List<Metadata>();
try // implement proper error handling
{
Connection.Open();
metadata = Connection.Query<Metadata>(query).ToList();
Connection.Close();
}
catch(Exception ex)
{
// error here
}
return metadata;
}
Some useful links:
Dapper Github
Dapper Tutorial
Converting it to generic method: (not tested right now)
public List<T> RunSelectQuery<T>(string query)
{
try // implement proper error handling
{
Connection.Open();
metadata = Connection.Query<T>(query).ToList();
Connection.Close();
}
catch(Exception ex)
{
// error here
}
return metadata;
}
and use something like this below:
List<Metadata> myMetadata = RunSelectQuery<Metadata>(query);
I prefer a pattern more like this:
public class MySqlDb
{
//1. This should not be public!
// Keeping it private forces other code to go through your public methods,
// rather than using the connection directly.
// Even better if the class knows how to read the string from a
// config rile rather than accepting it via the constructor.
//2. Don't save a connection object for re-use.
// ADO.Net has a connection pooling feature that works when you
// create new objects for most queries
private string ConnectionString { get; set;}
public MySqlDb(string connectionString)
{
ConnectionString = connectionString;
}
//1. Use IEnumerable instead of List
// ...don't pull all of the results into memory at the same time until/unless you really have to.
//2. Methods that accept query strings should also accept parameters.
// Otherwise you are forced to build sql strings in insecure crazy-vulnerable ways
public IEnumerable<Metadata> RunSelectQueryForMetadata(string query, IEnumerable<MySqlParameter> parameters)
{
using (var cn = new MySqlConnection(ConnectionString))
using (var cmd = new MySqlCommand(query, cn))
{
if (parameters != null)
{
cmd.Parameters.AddRange(parameters.ToArray());
}
cn.Open();
using(var rdr = cmd.ExecuteReader())
{
while(rdr.Read())
{
yield return new Metadata {
Id = rdr["id"],
Title = rdr["title"],
Sku = rdr["sku"],
IsLive = rdr["islive"],
};
}
rdr.Close();
}
}
}
}
Ultimately, the ideal is for the RunSelectQuery__() method to be generic and private, and for public methods to not accept SQL statements. The goal is to force all SQL in your program to live in the MySqlDb class. Each query has a method that accepts specific typed inputs, and returns typed output. The reason you have that goal is to make it easy to manage your database access and easy to audit that all of your SQL code is safely using parameters (and not vulnerable to sql injection attacks! ). You want something like this:
//updated to remove the earlier explanatory comments
// and show example methods for isolating SQL from the rest of the application.
public class MySqlDb
{
private string ConnectionString { get; set;}
private string ReadConnectionStringFromConfigFile()
{
//TODO
throw NotImplementedException();
}
public MySqlDb()
{
ConnectionString = ReadConnectionStringFromConfigFile();
}
//This is now PRIVATE and generic, and allows for parameterized queries
private IEnumerable<T> RunSelectQuery(string query, Func<IDataReader, T> translateRecord, IEnumerable<MySqlParameter> parameters)
{
using (var cn = new MySqlConnection(ConnectionString))
using (var cmd = new MySqlCommand(query, cn))
{
if (parameters != null)
{
cmd.Parameters.AddRange(parameters.ToArray());
}
cn.Open();
using(var rdr = cmd.ExecuteReader())
{
while(rdr.Read())
{
yield return translateRecord(rdr);
}
rdr.Close();
}
}
}
////// Example methods showing how to use the generic method above
// These methods are the only public part of your class
public MetaData GetMetaDataById(int ID)
{
string sql = "SELECT * FROM MetatData WHERE ID= #ID";
var parameters = new List<MySqlParameters> {
new MySqlParameter() {
ParameterName = "#ID",
MySqlDbType = MySqlDbType.Int32,
Value = ID
}
};
return RunSelectQuery<MetaData>(sql, parameters, r =>
new Metadata {
Id = r["id"],
Title = r["title"],
Sku = r["sku"],
IsLive = r["islive"],
}).FirstOrDefault();
}
public IEnumerable<MetaData> GetAllMetaData()
{
string sql = "SELECT * FROM MetatData";
return RunSelectQuery<MetaData>(sql, null, r =>
new Metadata {
Id = r["id"],
Title = r["title"],
Sku = r["sku"],
IsLive = r["islive"],
});
}
public User GetUserByID(int ID)
{
string sql = "SELECT * FROM User WHERE ID= #ID";
var parameters = new List<MySqlParameters> {
new MySqlParameter() {
ParameterName = "#ID",
MySqlDbType = MySqlDbType.Int32,
Value = ID
}
};
return RunSelectQuery<User>(sql, parameters, r =>
new Metadata {
Id = r["id"],
UserName = r["UserName"],
Age = r["Age"],
Address = r["Address"],
}).FirstOrDefault();
}
public User GetUserByUsername(string UserName)
{
string sql = "SELECT * FROM User WHERE Username= #UserName";
var parameters = new List<MySqlParameters> {
new MySqlParameter() {
ParameterName = "#UserName",
MySqlDbType = MySqlDbType.VarChar,
Size = 20, //guessing at username lenght
Value = UserName
}
};
return RunSelectQuery<User>(sql, parameters, r =>
new Metadata {
Id = r["id"],
UserName = r["UserName"],
Age = r["Age"],
Address = r["Address"],
}).FirstOrDefault();
}
public IEnumerable<User> FindUsersByAge(int Age)
{
string sql = "SELECT * FROM User WHERE Age = #Age";
var parameters = new List<MySqlParameters> {
new MySqlParameter() {
ParameterName = "#Age",
MySqlDbType = MySqlDbType.Int32,
Value = Age
}
};
return RunSelectQuery<User>(sql, parameters, r =>
new Metadata {
Id = r["id"],
UserName = r["UserName"],
Age = r["Age"],
Address = r["Address"],
});
}
}
In larger applications, you abstract this further into a separate project, with a private class for the lower-level methods that are private here, and a public class for each of the object types you use via that database. You might even go full-blown service-oriented architecture, where you get all your data via web service calls, and only the service layer talks directly to any database.
Of course, at this level you can also use a mirco-ORM like Dapper. Micro-ORMs will help you avoid re-writing the same mapping code over and over, and also help more with the INSERT/UPDATE side of data operations. Their goal is to take over as much of the boilerplate code for you as they can.
The advantage of a micro-ORM over a full ORM is it keeps you closer to the SQL. This is a good thing. Full-blown ORMs like Entity Framework or NHibernate effectively force you to learn a whole new language on top of the SQL, while mostly limiting you to basic SQL statements that often lose the advantages from the "relational" part of a relational database. Eventually, you often end up needing to understand and write complex raw SQL anyway to optimize performace. Micro-ORMs try to offer a happy-medium... taking away as much of the boiler plate code needed to talk to a database as they can, while still leaving you to write your own SQL.
While not tailored to using MySql and straight up sql, the below code snippets provide a means to do what you're asking using generics. Could use some improvements though...
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Data.General
{
public abstract class DataObject
{
protected abstract void Initialize(IDataRecord dataRow);
private static string _connectionString = "";
/// <summary>
/// Loads a single data object from the results of a stored procedure.
/// </summary>
protected static T ReadObject<T>(string procedureName, SqlParameter[] sqlParameters, Type dataType)
{
DataObject returnItem = null;
using (SqlConnection sqlConnection = new SqlConnection(GetConnectionString()))
using (SqlCommand command = BuildCommand(sqlConnection, procedureName, sqlParameters))
{
sqlConnection.Open();
//Execute the reader for the given stored proc and sql parameters
using (IDataReader reader = command.ExecuteReader())
{
//If we get no records back we'll still return null
while (reader.Read())
{
returnItem = (DataObject)Activator.CreateInstance(typeof(T));
returnItem.Initialize(reader);
break;
}
}
}
//Return our DataObject
return (T)Convert.ChangeType(returnItem, dataType);
}
/// <summary>
/// Reads a collection of data objects from a stored procedure.
/// </summary>
protected static List<T> ReadObjects<T>(string procedureName, SqlParameter[] sqlParameters)
{
//Get cached data if it exists
List<T> returnItems = new List<T>();
T dataObject;
using (SqlConnection sqlConnection = new SqlConnection(GetConnectionString()))
using (SqlCommand command = BuildCommand(sqlConnection, procedureName, sqlParameters, null))
{
sqlConnection.Open();
//Execute the reader for the given stored proc and sql parameters
using (IDataReader reader = command.ExecuteReader())
{
//If we get no records back we'll still return null
while (reader.Read())
{
dataObject = (T)Activator.CreateInstance(typeof(T));
(dataObject as DataObject).Initialize(reader);
returnItems.Add(dataObject);
}
}
}
//Return the DataObjects
return returnItems;
}
/// <summary>
/// Builds a SQL Command object that can be used to execute the given stored procedure.
/// </summary>
private static SqlCommand BuildCommand(SqlConnection sqlConnection, string procedureName, SqlParameter[] sqlParameters, SqlTransaction sqlTransaction = null)
{
SqlParameter param;
SqlCommand cmd = new SqlCommand(procedureName, sqlConnection);
if (sqlTransaction != null)
{
cmd.Transaction = sqlTransaction;
}
cmd.CommandType = CommandType.StoredProcedure;
// Add SQL Parameters (if any)
foreach (SqlParameter parameter in sqlParameters)
{
param = new SqlParameter(parameter.ParameterName, parameter.DbType);
param.Value = parameter.Value;
cmd.Parameters.Add(param);
}
return cmd;
}
private static string GetConnectionString()
{
return _connectionString;
}
public static void SetConnectionString(string connectionString)
{
_connectionString = connectionString;
}
}
}
namespace Data.Library
{
public class Metadata : General.DataObject
{
protected Data.Model.Metadata _metaData;
public Data.Model.Metadata BaseModel
{
get { return _metaData; }
set { _metaData = value; }
}
//Typically I have properties in here pointing to the Data.Model class
protected override void Initialize(System.Data.IDataRecord dataRow)
{
_metaData = new Model.Metadata();
_metaData.Id = Convert.ToInt32(dataRow["Id"].ToString());
_metaData.Title = (dataRow["Title"].ToString());
_metaData.Sku = (dataRow["Sku"].ToString());
_metaData.IsLive = Convert.ToBoolean(dataRow["IsLive"].ToString());
}
public static Metadata ReadByID(int id)
{
return General.DataObject.ReadObject<Metadata>("dbo.s_MetadataGet", new[] { new SqlParameter("#ID", id) },
typeof(Metadata));
}
public static Metadata[] ReadBySku(string sku)
{
List<Metadata> metaDatas = General.DataObject.ReadObjects<Metadata>("dbo.s_MetadataGetBySku", new[] { new SqlParameter("#Sku", sku) });
return metaDatas.ToArray();
}
}
}
namespace Data.Model
{
public class Metadata
{
public int Id { get; set; }
public string Title { get; set; }
public string Sku { get; set; }
public bool IsLive { get; set; }
}
}

populate dropdown list from a list of objects

In an attempt of building a 3-tier architecture c# asp.net application, I've started building a class that is database which is used for the connecting to the database, another class that is City which has a method for each column in the table cities, and a Cities class in which I have the GetCities method that creates a list of City objects and then use the DataSource wizard to set the control to use the data from GetCities().
All I get is blanks in the dropdown list. Any idea why?
public List<City> GetCities()
{
List<City> cities = new List<City>();
Database db = new Database();
SqlConnection conn = db.GetConnection();
String sql = "SELECT * FROM CITIES";
SqlCommand cmd = new SqlCommand(sql, conn);
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
City c = new City(reader.GetInt32(0), reader.GetString(1).ToString());
cities.Add(c);
}
db.CloseConnection();
return cities;
}
thanks
Did you set the DataTextField, DataValueField properties, and call DataBind?
At this point I would try to get the concept working as simply as possible, and then start adding things back in until you locate the problem. Start with a brand new page, add a DropDownList but don't touch the data source or change any properties, go directly into the codebehind and add this in Page_Load:
DropDownList1.DataValueField = "ID";
DropDownList1.DataTextField = "Name";
DropDownList1.DataSource = new[] {
new { ID = 1, Name = "Alice" },
new { ID = 2, Name = "Mike" },
new { ID = 3, Name = "John" }
};
DropDownList1.DataBind();
Does it work? It does for me. Then try to change DataValueField, DataTextField, and DataSource to work with your customer list. Is it broken now? Then you know the problem is in the customer list somewhere, not with the way you're binding the data.
Have you called DataBind() method on the object you want to be populated ?
The issue resided in the City class which after a close inspection I've realised that the constructor was assigning the parameter received incorrectly. It's now working. Thanks!
public class City
{
int id;
string name;
public City(int id, string name)
{
this.id = id;
this.name = name;
}
public int Id
{
get { return id; }
set { id = value; }
}
public String Name
{
get { return name; }
set { name = value; }
}
}

Trouble with my property using C#

I am having trouble with my property always being null in my app, but I believe that the problem may be deeper than that. The requirement is to have a data layer class that contains my connection string to my access database. This calls another class which pulls the database information and sets it back to the data layer class. I must then use ONLY the data layer class to get my records. The problem is that my property is always null. Here is the code for the data layer class:
{
class CustomerDL
{
OleDbConnection aConnection = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=CIS3341.accdb;");
string names;
public void initializeConnection()
{
Customer.initializeConnection(aConnection);
}
public string getNames
{
get { return names; }
set { names = value; }
}
}
}
And here is the other class:
class Customer
{
static OleDbConnection aConnection = null;
string names;
public static void initializeConnection(OleDbConnection aDbConnection)
{
aConnection = aDbConnection;
aConnection.Open();
getNames();
}
public static void getNames()
{
CustomerDL aCustomer = new CustomerDL();
OleDbDataAdapter myAdapter = new OleDbDataAdapter();
if (aConnection.State == ConnectionState.Closed)
{
aConnection.Open();
}
OleDbCommand cmd = aConnection.CreateCommand();
OleDbDataReader dbReader = null;
cmd.CommandText = "SELECT CustomerName FROM Customer";
dbReader = cmd.ExecuteReader();
while (dbReader.Read())
{
aCustomer.getNames += (string)dbReader["CustomerName"].ToString() + "\r\n";
}
dbReader.Close();
//return aCustomer ;
}
}
Now when i use this code on my form:
public partial class Form1 : Form
{
CustomerDL customer = new CustomerDL();
public Form1()
{
InitializeComponent();
customer.initializeConnection();
string fast = customer.getNames;
richTextBox1.Text = fast;
}
customer.getNames; is always null. Any ideas?
You aren't assigning anything to the proper instance of CustomerDL.
customer.getNames never gets accessed whatsoever. You are initializing your connection, but in that method you use a new CustomerDL: CustomerDL aCustomer = new CustomerDL();. You have to provide that instance to the static method for it to do something.
in CustomerDL the member names has the default value null, you can initialize it with string names = string.Empty;
You really should consolidate the Customer and CustomerDL classes into one class. There is too much duplication. So instead of having CustomerDL call Customer, just put the getnames() code in your CustomerDL class. And scrap all the static modifiers. By your form example, you are instantiating CustomerDL and calling methods on it. Make the class and its methods non-static, and this will work much better for you.
One of the problems that is preventing you from figuring this one out is your naming conventions...
You have both properties and methods named the same (I would leave the word "get" off of properties).
You have a "CustomerDL" object that you named "customer". The problem is you also have a "Customer" class.
You have a static method coded to do what you want, but you are never calling it.
IMHO if you take a little more care in your naming conventions, it will be a lot easier to troubleshoot these kinds of issues....There are a few things wrong with the code, but I quickly gave fixing it a shot. Hope it helps:
class CustomerDL
{
OleDbConnection aConnection = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=CIS3341.accdb;");
public string GetNames()
{
string NamesToReturn = "";
try
{
OleDbDataAdapter myAdapter = new OleDbDataAdapter();
if (aConnection.State == ConnectionState.Closed)
{
aConnection.Open();
}
OleDbCommand cmd = aConnection.CreateCommand();
OleDbDataReader dbReader = null;
cmd.CommandText = "SELECT CustomerName FROM Customer";
dbReader = cmd.ExecuteReader();
while (dbReader.Read())
{
NamesToReturn += (string)dbReader["CustomerName"].ToString() + "\r\n";
}
dbReader.Close();
catch(Exception ex)
{
}
finally
{
aConnection.Close(); //makes sure it closes...
}
return NamesToReturn;
}
}
Then you can do this:
class Customer
{
private CustomerDL customerData = new CustomerDL();
public string Names { get; set; }
public string FillNames()
{
this.Names = customerData.GetNames();
}
}
public partial class Form1 : Form
{
Customer customer = new Customer();
public Form1()
{
InitializeComponent();
customer.FillNames();
richTextBox1.Text = customer.Names;
}
}
Note: This code is very crude and I have not double checked it, but I beleive it will get you pointed in the right direction.

Categories

Resources