I am trying to get a little tool to work, for our little company.
This should fill data from a DataGridView into a SQL Server Standard database.
Reading out the SQL table is working fine, but I can't get the tool to write the values.
I get the error mentioned in the title.
Here the code:
var kdNummer = new SqlParameter("Kundennummer", SqlDbType.Int);
var kdName = new SqlParameter("Kundenname", SqlDbType.VarChar);
var kdMail = new SqlParameter("Kundenmail", SqlDbType.VarChar);
var kdTele = new SqlParameter("Telefon", SqlDbType.VarChar);
string kdquery = "INSERT INTO Kunden VALUES (#Kundennummer, #Kundenname, #Kundenmail, #Telefon)";
using (SqlConnection updatedb = new SqlConnection("Data Source=;Initial Catalog=updatedb;User ID=;Password="))
{
updatedb.Open();
for (int i = 0;i<dataGridView1.Rows.Count;i++)
{
using(SqlCommand NrDaten = new SqlCommand(kdquery, updatedb))
{
kdNummer.Value = dataGridView1.Rows[i].Cells["Kundennummer"].Value;
NrDaten.Parameters.Add(kdNummer);
NrDaten.ExecuteNonQuery();
}
using (SqlCommand NameDaten = new SqlCommand(kdquery, updatedb))
{
kdName.Value = dataGridView1.Rows[i].Cells["Kundenname"].Value;
NameDaten.Parameters.Add(kdName);
NameDaten.ExecuteNonQuery();
}
using (SqlCommand MailDaten = new SqlCommand(kdquery, updatedb))
{
kdMail.Value = dataGridView1.Rows[i].Cells["Kundenmail"].Value;
MailDaten.Parameters.Add(kdMail);
MailDaten.ExecuteNonQuery();
}
using (SqlCommand TeleDaten = new SqlCommand(kdquery, updatedb))
{
kdTele.Value = dataGridView1.Rows[i].Cells["Telefon"].Value;
TeleDaten.Parameters.Add(kdTele);
TeleDaten.ExecuteNonQuery();
}
}
updatedb.Close();
}
Your query requires 4 parameters, but you're always only setting one (also please note that in the SqlParameter you need to have the # sign as well). Thus you get an error about missing parameters. Your code should probably look like this:
var kdNummer = new SqlParameter("#Kundennummer", SqlDbType.Int);
var kdName = new SqlParameter("#Kundenname", SqlDbType.VarChar);
var kdMail = new SqlParameter("#Kundenmail", SqlDbType.VarChar);
var kdTele = new SqlParameter("#Telefon", SqlDbType.VarChar);
string kdquery = "INSERT INTO Kunden VALUES (#Kundennummer, #Kundenname, #Kundenmail, #Telefon)";
using (SqlConnection updatedb = new SqlConnection("..."))
{
updatedb.Open();
using (SqlCommand insert = new SqlCommand(kdquery, updatedb))
{
insert.Parameters.Add(kdName);
insert.Parameters.Add(kdNummer);
insert.Parameters.Add(kdMail);
insert.Parameters.Add(kdTele);
for (int i = 0;i<dataGridView1.Rows.Count;i++)
{
kdName.Value = dataGridView1.Rows[i].Cells["Kundenname"].Value;
kdNummer.Value = dataGridView1.Rows[i].Cells["Kundennummer"].Value;
kdMail.Value = dataGridView1.Rows[i].Cells["Kundenmail"].Value;
kdTele.Value = dataGridView1.Rows[i].Cells["Telefon"].Value;
insert.ExecuteNonQuery();
}
}
}
Or even shorter:
string kdquery = "INSERT INTO Kunden VALUES (#Kundennummer, #Kundenname, #Kundenmail, #Telefon)";
using (SqlConnection updatedb = new SqlConnection("..."))
{
updatedb.Open();
for (int i = 0;i<dataGridView1.Rows.Count;i++)
{
using (SqlCommand insert = new SqlCommand(kdquery, updatedb))
{
insert.Parameters.AddWithValue("#Kundenname", dataGridView1.Rows[i].Cells["Kundenname"].Value);
insert.Parameters.AddWithValue("#Kundennummer", dataGridView1.Rows[i].Cells["Kundennummer"].Value);
insert.Parameters.AddWithValue("#Kundenmail", dataGridView1.Rows[i].Cells["Kundenmail"].Value);
insert.Parameters.AddWithValue("#Telefon", dataGridView1.Rows[i].Cells["Telefon"].Value);
insert.ExecuteNonQuery();
}
}
}
EDIT: I modified the long version of the code for maximum re-use of instances. Otherwise you get the errors mentioned in your comment.
Related
The below code throws an error
The UserId, Password or Account is invalid.
on the code line adapter.Fill(ds);
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Teradata.Client.Provider;
using System.Data;
using System.Diagnostics;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
TdConnectionStringBuilder connectionStringBuilder = new TdConnectionStringBuilder();
connectionStringBuilder.DataSource = "URL";
connectionStringBuilder.Database = "DB";
connectionStringBuilder.UserId = "USERNAME";
connectionStringBuilder.Password = "PASSWORD";
connectionStringBuilder.AuthenticationMechanism = "LDAP";
TdConnection cn = new TdConnection();
cn.ConnectionString = connectionStringBuilder.ConnectionString;
cn.Open();
TdCommand cmd = new TdCommand("EXEC MACRO", cn);
TdDataReader reader = cmd.ExecuteReader();
TdDataAdapter adapter = new TdDataAdapter(cmd.CommandText, cn.ConnectionString);
DataSet ds = new DataSet();
adapter.Fill(ds);
// myLabel.Text= ds.Tables[0].Rows[0]["event_id"].ToString();
cmd.Dispose();
cn.Close();
}
}
However, the below code works perfectly fine and returns value as expected.
TdConnectionStringBuilder connectionStringBuilder = new TdConnectionStringBuilder();
connectionStringBuilder.DataSource = "URL";
connectionStringBuilder.Database = "DB";
connectionStringBuilder.UserId = "USERNAME";
connectionStringBuilder.Password = "PASSWORD";
connectionStringBuilder.AuthenticationMechanism = "LDAP";
TdConnection cn = new TdConnection();
cn.ConnectionString = connectionStringBuilder.ConnectionString;
cn.Open();
TdCommand cmd = new TdCommand("Show table DB.TABLE1", cn);
String customers = (String)cmd.ExecuteScalar();
MeanTime.Text = customers;
cmd.Dispose();
cn.Close();
The user ID, Password, Datasource etc are all same yet it fails on 1st code but runs properly on 2nd.
When calling procs and macros you can use the TDCommand.ExecuteNonQuery.
UPDATE: Upon further reading here it looks like you can include the CALL when using the Stored Procedure commandtype. The proper Commandtype for a Macro execution is System.Data.CommandType.Text and you probably need the EXEC
For reference, with parameter binding and a procedure, here's a working example below. Some small tweaks would need to be made (as mentioned above) for a macro execution.
//create a new td connection
TdConnection cn = new TdConnection();
//Build the connection string
TdConnectionStringBuilder connectionStringBuilder = new TdConnectionStringBuilder();
connectionStringBuilder.DataSource = "serveraddress";
connectionStringBuilder.Database = "defaultdatabase";
connectionStringBuilder.UserId = "username";
connectionStringBuilder.Password = "password";
connectionStringBuilder.AuthenticationMechanism = "LDAP";
connectionStringBuilder.CommandTimeout = 120;
//Open the connection
cn.ConnectionString = connectionStringBuilder.ConnectionString;
cn.Open();
// Initialize TdCommand from the tdconnection
TdCommand cmd = cn.CreateCommand();
//CommandText is set to Stored Procedure name, in this case,
//.NET Data Provider will generate the CALL statement.
cmd.CommandText = "yourdatabasename.yourprocname";
cmd.CommandType = CommandType.StoredProcedure;
// Create Input Parameter required by this procedure
TdParameter InParm1 = cmd.CreateParameter();
InParm1.Direction = ParameterDirection.Input;
InParm1.DbType = DbType.String;
InParm1.Size = 20;
InParm1.Value = "yourparamvalue";
//and bind it
cmd.Parameters.Add(InParm1);
//------------OPTION 1 CATCHING AN OUTPUT PARAMETER---------------------
//If you are catching an output parameter from a proc then create here:
// Create Output Parameter.
TdParameter OutParm = cmd.CreateParameter();
OutParm.Direction = ParameterDirection.Output;
OutParm.ParameterName = "myOutputParam";
OutParm.DbType = DbType.String;
OutParm.Size = 200;
cmd.Parameters.Add(OutParm);
// Run it up
cmd.ExecuteReader()
//if this is returning a single value you can grab it now:
myOutput = OutParm.Value.ToString();
//------------OPTION 2 CATCHING A RECORDSET-----------------------------
//list based on class set in seperate model
List<myClass> l_myclass = new List<myClass>();
//run it up and catch into a TDDataRead
using (TdDataReader r = cmd.ExecuteReader())
{
if (r.HasRows)
{
//Loop the result set and catch the values in the list
while (r.Read())
{
//"myclass" class defined in a seperate model
//Obviously you could do whatever you want here, but
//creating a list on a class where the column1-column4 is defined makes short work of this.
//Then you can dump the whole l_myclass as json back to the client if you want.
myClass i = new myClass();
i.column1 = (!r.IsDBNull(0)) ? r.GetString(0) : string.Empty;
i.column2 = (!r.IsDBNull(1)) ? r.GetString(1) : string.Empty;
i.column3 = (!r.IsDBNull(2)) ? r.GetString(2) : string.Empty;
i.column4 = (!r.IsDBNull(3)) ? r.GetString(3) : string.Empty;
l_myClass.Add(i);
}
}
}
//Dump the list out as json (for example)
return Json(l_myClass, System.Web.Mvc.JsonRequestBehavior.AllowGet);
I've only, personally, used this on procedures, but the documentation I've read suggests that this is the correct route for macros as well.
I'm making a web app, for tracking Fedex shipments, I currently have about 10,000-15,000 packages daily.
I integrated Fedex Api in my System but it takes more tan 20 minutes to get the status of only 1300 packages. Is there a Way to make this faster? I read that you can send 30 packages in one request but can't find a Way to make it work.
Here is a link to another question, that I found but didn't get it to work
Requesting many tracking numbers with Fedex SOAP API with PHP
CODE
{
TrackRequest request = new TrackRequest();
request.WebAuthenticationDetail = new WebAuthenticationDetail();
request.WebAuthenticationDetail.UserCredential = new WebAuthenticationCredential();
request.WebAuthenticationDetail.UserCredential.Key = ""; // Replace "XXX" with the Key
request.WebAuthenticationDetail.UserCredential.Password = ""; // Replace "XXX" with the Password
request.WebAuthenticationDetail.ParentCredential = new WebAuthenticationCredential();
request.WebAuthenticationDetail.ParentCredential.Key = ""; // Replace "XXX" with the Key
request.WebAuthenticationDetail.ParentCredential.Password = ""; // Replace "XXX"
request.ClientDetail = new ClientDetail();
request.ClientDetail.AccountNumber = ""; // Replace "XXX" with the client's account number
request.ClientDetail.MeterNumber = ""; // Replace "XXX" with the client's meter number
request.TransactionDetail = new TransactionDetail();
request.TransactionDetail.CustomerTransactionId = "***Track Request using VC#***"; //This is a reference field for the customer. Any value can be used and will be provided in the response.
request.Version = new VersionId();
// Tracking information
request.SelectionDetails = new TrackSelectionDetail[1] { new TrackSelectionDetail() };
request.SelectionDetails[0].PackageIdentifier = new TrackPackageIdentifier();
request.SelectionDetails[0].PackageIdentifier.Value = TrackNumberGlobal; //"787883551221" Replace "XXX" with tracking number or door tag
request.SelectionDetails[0].PackageIdentifier.Type = TrackIdentifierType.TRACKING_NUMBER_OR_DOORTAG;
request.ProcessingOptions = new TrackRequestProcessingOptionType[1];
request.ProcessingOptions[0] = TrackRequestProcessingOptionType.INCLUDE_DETAILED_SCANS;
return request;
}
private void TrackReplyy(TrackReply reply)
{
foreach (CompletedTrackDetail completedTrackDetail in reply.CompletedTrackDetails)
{
foreach (TrackDetail trackDetail in completedTrackDetail.TrackDetails)
{
SqlCommand cos = new SqlCommand();
cos.CommandText = "Update estatus_fedex SET estadofedex = #estado WHERE fedextracking = #track";
cos.Parameters.AddWithValue("#estado", trackDetail.StatusDetail.Description);
cos.Parameters.AddWithValue("#track", TrackNumberGlobal);
cos.CommandType = CommandType.Text;
cos.Connection = sqlConn;
cos.ExecuteNonQuery();
if (trackDetail.Events != null)
{
foreach (TrackEvent trackevent in trackDetail.Events)
{
if(trackevent.StatusExceptionCode != null)
{
SqlCommand cmd2 = new SqlCommand();
cmd2.CommandText = "UPDATE estatus_fedex SET ExcpetionCode = #codigo WHERE fedextracking = #param2";
cmd2.Parameters.AddWithValue("#codigo", trackevent.StatusExceptionCode);
cmd2.Parameters.AddWithValue("#param2", TrackNumberGlobal);
cmd2.CommandType = CommandType.Text;
cmd2.Connection = sqlConn;
cmd2.ExecuteNonQuery();
if (trackevent.TimestampSpecified)
{
SqlCommand insert = new SqlCommand();
insert.CommandText = "INSERT INTO EstatusFedexHistorial(FedexTracking,EstadoFedex_Hist,ExceptionCode_Hist,Tiempo_Hist,EventDescription) VALUES (#Track,#Estado,#Excepcion,#Tiempo,#Evento)";
insert.Parameters.AddWithValue("#Track", TrackNumberGlobal);
insert.Parameters.AddWithValue("#Estado", trackDetail.StatusDetail.Description);
insert.Parameters.AddWithValue("#Excepcion", trackevent.StatusExceptionCode);
insert.Parameters.AddWithValue("#Tiempo", trackevent.Timestamp);
insert.Parameters.AddWithValue("#Evento", trackevent.EventDescription);
insert.CommandType = CommandType.Text;
insert.Connection = sqlConn;
insert.ExecuteNonQuery();
}
}
else
{
if (trackevent.TimestampSpecified)
{
SqlCommand sqlc = new SqlCommand();
sqlc.CommandText = "INSERT INTO EstatusFedexHistorial(FedexTracking,EstadoFedex_Hist,Tiempo_Hist,EventDescription) VALUES (#Track,#Estado,#Tiempo,#Evento)";
sqlc.Parameters.AddWithValue("#Track", TrackNumberGlobal);
sqlc.Parameters.AddWithValue("#Estado", trackDetail.StatusDetail.Description);
sqlc.Parameters.AddWithValue("#Tiempo", trackevent.Timestamp);
sqlc.Parameters.AddWithValue("#Evento", trackevent.EventDescription);
sqlc.CommandType = CommandType.Text;
sqlc.Connection = sqlConn;
sqlc.ExecuteNonQuery();
}
}
}
}
}
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "UPDATE EstatusFedexHistorial SET Manifiesto = #manifiesto WHERE FedexTracking = #track";
cmd.Parameters.AddWithValue("#manifiesto", manifiesto);
cmd.Parameters.AddWithValue("#track", TrackNumberGlobal);
cmd.CommandType = CommandType.Text;
cmd.Connection = sqlConn;
cmd.ExecuteNonQuery();
}
}
You need to do something like the following code where trackingNumbers is an array of tracking numbers.
request.SelectionDetails = new TrackSelectionDetail[trackingNumbers.Length];
for (int i = 0; i < trackingNumbers.Length; i++)
{
request.SelectionDetails[i] = new TrackSelectionDetail()
{
PackageIdentifier = new TrackPackageIdentifier
{
Value = trackingNumbers[i],
Type = TrackIdentifierType.TRACKING_NUMBER_OR_DOORTAG
}
};
}
I coded a web service connecting to MS-Sql server and getting the results from a stored procedure. My below code is getting only the first result of procedure, but I need all results in the response xml file. I think that I need to use data adapter, data reader, data fill, etc.. something like this. But I could not succeed. I would appreciate any help:
PS: Info.cs class already created.
[WebMethod]
public Info NumberSearch2(string no)
{
Info ourInfo = new Info();
string cs = ConfigurationManager.ConnectionStrings["DBBaglan"].ConnectionString;
using (SqlConnection Con = new SqlConnection(cs))
{
SqlCommand cmd = new SqlCommand(cmdText: "NumberSearch", connection: Con)
{
CommandType = CommandType.StoredProcedure
};
SqlParameter parameter = new SqlParameter
{
ParameterName = "#no",
Value = no
};
cmd.Parameters.Add(parameter);
Con.Open();
SqlDataReader dr = cmd.ExecuteReader();
DataSet ds = new DataSet();
while (dr.Read())
{
ourInfo.PartNo = dr["PartNo"].ToString();
ourInfo.BrandNo = dr["BrandNo"].ToString();
ourInfo.Manufacturer = dr["Manufacturer"].ToString();
ourInfo.Country = dr["Country"].ToString();
ourInfo.ReferenceNo = dr["ReferenceNo"].ToString();
}
}
return ourInfo;
}
After #David 's recommendation:
[WebMethod]
//public Info NumberSearch2(string no)
public List<Info> NumberSearch2(string no)
{
Info ourInfo = new Info();
var ourInfos = new List<Info>();
string cs = System.Configuration.ConfigurationManager.ConnectionStrings["DBBaglan"].ConnectionString;
using (System.Data.SqlClient.SqlConnection Con = new System.Data.SqlClient.SqlConnection(cs))
{
System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(cmdText: "NumberSearch", connection: Con)
{
CommandType = System.Data.CommandType.StoredProcedure
};
System.Data.SqlClient.SqlParameter parameter = new System.Data.SqlClient.SqlParameter
{
ParameterName = "#no",
Value = no
};
cmd.Parameters.Add(parameter);
Con.Open();
System.Data.SqlClient.SqlDataReader dr = cmd.ExecuteReader();
DataSet ds = new DataSet();
while (dr.Read())
{
var ourInfos = new Info();
ourInfo.PartNo = dr["PartNo"].ToString();
ourInfo.BrandNo = dr["BrandNo"].ToString();
ourInfo.Manufacturer = dr["Manufacturer"].ToString();
ourInfo.Country = dr["Country"].ToString();
ourInfo.ReferenceNo = dr["ReferenceNo"].ToString();
ourInfos.Add(ourInfo);
}
}
return ourInfos;
}
You're returning a single Info object. If you want a collection of them, return a List<Info> instead. Change the method signature:
public List<Info> NumberSearch2(string no)
Declare the object to return:
var ourInfos = new List<Info>();
Within your loop, add each record to the list:
while (dr.Read())
{
var ourInfo = new Info();
ourInfo.PartNo = dr["PartNo"].ToString();
ourInfo.BrandNo = dr["BrandNo"].ToString();
ourInfo.Manufacturer = dr["Manufacturer"].ToString();
ourInfo.Country = dr["Country"].ToString();
ourInfo.ReferenceNo = dr["ReferenceNo"].ToString();
ourInfos.Add(ourInfo);
}
And return the list:
return ourInfos;
I am trying to insert an image into Postgres and retrieve that image from postgresql using C#.
I have two columns in my table: memberid (character varying) and member_photo (bytea)
Here is my code to insert the image:
using (FileStream pgFileStream = new FileStream("D:\\Capture.jpg", FileMode.Open, FileAccess.Read))
{
using (BinaryReader pgReader = new BinaryReader(new BufferedStream(pgFileStream)))
{
NpgsqlCommand command = new NpgsqlCommand();
byte[] ImgByteA = pgReader.ReadBytes(Convert.ToInt32(pgFileStream.Length));
command.CommandText = "insert into membermaster (memberid, member_photo) VALUES ('65', #Image)";
command.Connection = Program.conn;
Program.conn.Close();
Program.conn.Open();
//command.Parameters.Add(new NpgsqlParameter("Image", ImgByteA));
command.Parameters.Add("#Image", ImgByteA).Value = ImgByteA;
command.ExecuteNonQuery();
Program.conn.Close();
}
}
Here is my code to retrieve the image
NpgsqlCommand command = new NpgsqlCommand();
command.CommandText = "select member_photo from membermaster where memberid='65'";
command.Connection = Program.conn;
try
{
Program.conn.Close();
Program.conn.Open();
byte[] productImageByte = command.ExecuteScalar() as byte[];
if (productImageByte != null)
{
using (MemoryStream productImageStream = new System.IO.MemoryStream(productImageByte))
{
ImageConverter imageConverter = new System.Drawing.ImageConverter();
pictureBox1.Image = imageConverter.ConvertFrom(productImageByte) as System.Drawing.Image;
// image.Save(imageFullPath, System.Drawing.Imaging.ImageFormat.Jpeg);
pictureBox1.Image = System.Drawing.Image.FromStream(productImageStream);
}
}
}
catch
{
Program.conn.Close();
throw;
}
The code to insert the image is working fine, but I can't show this image in a picturebox.
I get an error :
Parameter is not valid
Please help me solve this problem
AFAIK you cannot retrieve a byte[] using ExecuteScalar. You should use ExecuteReader instead. Just to be on the safe side when inserting parameters, I prefer to specify types myself, so my insert looks like this:
using (var conn = new NpgsqlConnection(connString))
{
string sQL = "insert into picturetable (id, photo) VALUES(65, #Image)";
using (var command = new NpgsqlCommand(sQL, conn))
{
NpgsqlParameter param = command.CreateParameter();
param.ParameterName = "#Image";
param.NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Bytea;
param.Value = ImgByteA;
command.Parameters.Add(param);
conn.Open();
command.ExecuteNonQuery();
}
}
I can then retrieve and load the image like this:
using (var conn = new NpgsqlConnection(connString))
{
string sQL = "SELECT photo from picturetable WHERE id = 65";
using (var command = new NpgsqlCommand(sQL, conn))
{
byte[] productImageByte = null;
conn.Open();
var rdr = command.ExecuteReader();
if (rdr.Read())
{
productImageByte = (byte[])rdr[0];
}
rdr.Close();
if (productImageByte != null)
{
using (MemoryStream productImageStream = new System.IO.MemoryStream(productImageByte))
{
ImageConverter imageConverter = new System.Drawing.ImageConverter();
pictureBox1.Image = imageConverter.ConvertFrom(productImageByte) as System.Drawing.Image;
}
}
}
}
I do not know if specifying the datatype on insert makes any difference, so try just retrieving using a Reader first. If that doesn't work, then I suggest changing your insert routine to something like mine.
Please note in my example id is an integer, not a character varying!
While the code in the accepted answer is working, it is not true that you cannot use ExecuteScalar. It might have been an issue in older versions, but using Npgsql 6.0.7 the following works:
public static async Task<byte[]?> GetByteaAsync(int id, string connectionString) {
byte[]? result = null;
await using (var con = new NpgsqlConnection(connectionString)) {
await con.OpenAsync();
await using (var cmd = new NpgsqlCommand("SELECT field_name from table_name where id=#id", con) {CommandType = CommandType.Text}) {
cmd.Parameters.Add("#id", NpgsqlDbType.Integer).Value = id;
result = ((byte[]?) await cmd.ExecuteScalarAsync());
}
await con.CloseAsync();
}
return result;
}
So i need to pass a list from this method:
[WebMethod]
public List<SLA_ClassLibrary.SLA_Class.ReadAtm> ReadAtm()
{
var AtmReadList = new List<SLA_ClassLibrary.SLA_Class.ReadAtm>();
using (SqlConnection Conn = new SqlConnection(ConfigurationManager.ConnectionStrings["SLAdb"].ConnectionString))
{
using (Conn)
{
Conn.Open();
string SQLReadAtm = "Select * from ATM;";
SqlCommand ReadAtmCmd = new SqlCommand(SQLReadAtm, Conn);
SqlDataReader reader = ReadAtmCmd.ExecuteReader();
while (reader.Read())
{
AtmReadList.Add(new SLA_ClassLibrary.SLA_Class.ReadAtm
{
idatm = reader.GetInt32(reader.GetOrdinal("IDATM")),
District_Region = reader.GetString(reader.GetOrdinal("District_Region")),
Local = reader.GetString(reader.GetOrdinal("Local")),
IsUp = reader.GetBoolean(reader.GetOrdinal("IsUp"))
});
}
}
return AtmReadList;
}
}
to a website table in MVC, but i'm having problems on how to go about doing this.
I can't pass the "return AtmReadList" to a List<> so i have no idea on how to do this.
Any way to do this?