I currently have a query where I am getting data from 2 different databases which is getting appended to one list called "accountbuys".
My first table has three data entry(3 accounts which want to buy stocks
The next table with 17 data points(17 stocks to buy)
I am merging these tables and getting output
However,the output I want , should have 17 data points repeated each time for the 3 different accounts, so that the end user can drill down and buy whichever stock he wants
PS: If what I am trying to ask is not clear, please be polite and tell me so. Please try not to be rude, I am still learning and new to StackExchange!
This is my code :`
public List<BuySellModel> GetBuyDataWthAccount()
{
List<BuySellModel> accountbuys = new List<BuySellModel>();
using (SqlConnection connectionreit = new SqlConnection(HubConnection))
using (SqlConnection connection = new SqlConnection(PMConnection))
{
connectionhub.Open();
connection.Open();
SqlCommand command3 = new SqlCommand(#"SELECT distinct(table1.name) as 'Symbol' ,table2.Segment as 'Segment',table2.AllocationAmount as 'AllocationAmount',table2.PX_LAST as 'Price',
table1.CUR_MKT_CAP as 'CMC',table1.FCFY_WITH_CUR_MKT_CAP as 'FCMC',table1.ROIC as 'ROIC', table1.ROICDELTA as 'ROICD' FROM View_REIT_Model_And_Holdings as table1
INNER JOIN [MostRecentlyInModelSelected] as table2
ON table1.name = table2.Ticker
WHERE table1.AllocationAmount != -1 AND
NOT EXISTS (SELECT NULL FROM [ViewPCData] as table3 WHERE table1.name = table3.Symbol AND table2.Segment = table3.SubsectorDescription AND table3.Objective = 'REITS' AND table3.SectorDescription != 'NULL' AND table3.SubsectorDescription != 'NULL')",
connectionreit);
command3.CommandType = CommandType.Text;
SqlCommand command4 = new SqlCommand("SELECT PortfolioAccountNumber, PortfolioDescription, SUM(TotalValue) as 'TotalValue' FROM [ViewPCData] WHERE Objective = 'REITS' GROUP BY PortfolioAccountNumber,PortfolioDescription", connection);
command4.CommandType = CommandType.Text;
var reader = command3.ExecuteReader();
var reader1 = command4.ExecuteReader();
if (reader1.HasRows)
{
while (reader1.Read())
{
BuySellModel accountb = new BuySellModel();
accountb.PortfolioAccount = reader1.GetString(reader1.GetOrdinal("PortfolioAccountNumber"));
accountb.PortfolioDescription = reader1.GetString(reader1.GetOrdinal("PortfolioDescription"));
accountb.AccountAmount = reader1.GetDecimal(reader1.GetOrdinal("TotalValue"));
accountbuys.Add(accountb);
if (reader.HasRows)
{
//foreach(var account in accountbuys)
//{
while (reader.Read())
{
BuySellModel buy = new BuySellModel();
buy.Symbol = reader.GetString(reader.GetOrdinal("Symbol"));
buy.Segment = reader.GetString(reader.GetOrdinal("Segment"));
//if (accountNumber == "soand os")
//{
// 1/3 of totalaccountvalue
buy.AllocationAmount = (reader.GetDouble(reader.GetOrdinal("AllocationAmount")));
//}
buy.Price = reader.GetDouble(reader.GetOrdinal("Price"));
buy.MarketValue = reader.GetDouble(reader.GetOrdinal("CMC"));
buy.FCFY = reader.GetDouble(reader.GetOrdinal("FCMC"));
buy.ROIC = reader.GetDouble(reader.GetOrdinal("ROIC"));
buy.ROICdelta = reader.GetDouble(reader.GetOrdinal("ROICD"));
buy.Buy = true;
//account1 = account.accountnumber;
accountbuys.Add(buy);
}
//} //for loop
}
} // accounts
} //reader1.hasrows
connectionhub.Close();
connection.Close();
}
return accountbuys;
}
EDIT:
Split the tables into two different lists and merged them later. This is working well now. Seems good for scaling too.
public List<BuySellModel> GetBuyDataWthAccount()
{
List<BuySellModel> accountbuys = new List<BuySellModel>();
List<Account> accounts = new List<Account>();
using (SqlConnection connection = new SqlConnection(PMConnection))
{
connection.Open();
SqlCommand command3 = new SqlCommand(#"SELECT distinct(table1.name) as 'Symbol' ,table2.Segment as 'Segment',table2.AllocationAmount as 'AllocationAmount',table2.PX_LAST as 'Price',
table1.CUR_MKT_CAP as 'CMC',table1.FCFY_WITH_CUR_MKT_CAP as 'FCMC',table1.ROIC as 'ROIC', table1.ROICDELTA as 'ROICD' FROM View_Model_And_Holdings as table1
INNER JOIN [MostRecentlyInModelSelected] as table2
ON table1.name = table2.Ticker
WHERE table1.AllocationAmount != -1 AND
NOT EXISTS (SELECT NULL FROM [ViewPCData] as table3 WHERE table1.name = table3.Symbol AND table2.Segment = table3.SubsectorDescription AND table3.Objective = 'STOCKS' AND table3.SectorDescription != 'NULL' AND table3.SubsectorDescription != 'NULL')",
connectionreit);
command3.CommandType = CommandType.Text;
SqlCommand command4 = new SqlCommand("SELECT PortfolioDetail , SUM(TotalValue) as 'TotalValue' FROM [ViewPCData] WHERE Objective = 'STOCKS' GROUP BY PortfolioAccountNumber,PortfolioDescription", connection);
command4.CommandType = CommandType.Text;
var reader = command3.ExecuteReader();
var reader1 = command4.ExecuteReader();
if (reader1.HasRows)
{
while (reader1.Read())
{
Account accountb = new Account();
accountb.PortfolioDetail = reader1.GetString(reader1.GetOrdinal("PortfolioDetail"));
// accountb.PortfolioDescription = reader1.GetString(reader1.GetOrdinal("PortfolioDescription"));
accountb.AccountAmount = reader1.GetDecimal(reader1.GetOrdinal("TotalValue"));
accounts.Add(accountb);
}
}
//List<BuyReits> buys = new List<BuyReits>();
if (reader.HasRows && accounts.Count > 0)
{
while (reader.Read())
{
foreach (var acc in accounts)
{
BuySellModel buy = new BuySellModel();
buy.Symbol = reader.GetString(reader.GetOrdinal("Symbol"));
buy.Segment = reader.GetString(reader.GetOrdinal("Segment"));
buy.AllocationAmount = (reader.GetDouble(reader.GetOrdinal("AllocationAmount")));
buy.Price = reader.GetDouble(reader.GetOrdinal("Price"));
//buy.Quantity = reader.GetInt32((reader.GetOrdinal("AllocationAmount"))/(reader.GetOrdinal("Price")));
buy.MarketValue = reader.GetDouble(reader.GetOrdinal("CMC"));
buy.FCFY = reader.GetDouble(reader.GetOrdinal("FCMC"));
buy.ROIC = reader.GetDouble(reader.GetOrdinal("ROIC"));
buy.ROICdelta = reader.GetDouble(reader.GetOrdinal("ROICD"));
buy.Buy = true;
buy.PortfolioAccount = acc.PortfolioDetail;
buy.AccountAmount = acc.AccountAmount;
accountbuys.Add(buy);
}
}
}
connection.Close();
}
return accountbuys;
}
The following provides the cross join in the C# layer (not saying it is the best possible solution, but it gets you closer to ready):
using (SqlConnection connectionhub = new SqlConnection(HubConnection))
using (SqlConnection connection = new SqlConnection(PMConnection))
{
connectionhub.Open();
connection.Open();
SqlCommand command3 = new SqlCommand(#"
SELECT distinct(table1.name) as 'Symbol',
table2.Segment as 'Segment',
table2.AllocationAmount as 'AllocationAmount',
table2.PX_LAST as 'Price',
table1.CUR_MKT_CAP as 'CMC',
table1.FCFY_WITH_CUR_MKT_CAP as 'FCMC',
table1.ROIC as 'ROIC',
table1.ROICDELTA as 'ROICD'
FROM View_REIT_Model_And_Holdings as table1
INNER JOIN [MostRecentlyInModelSelected] as table2
ON table1.name = table2.Ticker
WHERE table1.AllocationAmount != -1
AND NOT EXISTS (SELECT NULL
FROM [ViewPCData] as table3
WHERE table1.name = table3.Symbol
AND table2.Segment = table3.SubsectorDescription
AND table3.Objective = 'REITS'
AND table3.SectorDescription != 'NULL'
AND table3.SubsectorDescription != 'NULL')",
connectionreit);
command3.CommandType = CommandType.Text;
SqlCommand command4 = new SqlCommand(#"
SELECT PortfolioAccountNumber,
PortfolioDescription,
SUM(TotalValue) as 'TotalValue'
FROM [ViewPCData]
WHERE Objective = 'REITS'
GROUP BY PortfolioAccountNumber, PortfolioDescription", connection);
command4.CommandType = CommandType.Text;
var stocksDS = new DataSet();
var stocksDA = new System.Data.SqlClient.SqlDataAdapter();
stocksDA.SelectCommand = command3
stocksDA.Fill(stocksDS, "stocks");
var acctsDS = new DataSet();
var acctsDA = new System.Data.SqlClient.SqlDataAdapter();
acctsDA.SelectCommand = command4
acctsDA.Fill(acctsDS, "accts");
var stocks = stocksDS.Tables["stocks"].AsEnumerable();
var accts = acctsDS.Tables["accts"].AsEnumerable();
var results = (from stocksDR in stocks
from acctsDR in accts
select new BuySellModel {
PortfolioAccount = acctsDR["PortfolioAccountNumber"],
PortfolioDescription = acctsDR["PortfolioAccountDescription"],
AccountAmount = acctsDR["TotalValue"],
Symbol = stocksDR["Symbol"],
Segment = stocksDR["Segment"],
AllocationAmount = stocksDR["AllocationAmount"],
Price = stocksDR["Price"],
MarketValue = stocksDR["CMC"],
FCFY = stocksDR["FCMC"],
ROIC = stocksDR["ROIC"],
ROICdelta = stocksDR["ROICD"],
Buy = true
});
foreach (BySellModel buy in results) {
accountBuys.Add(buy);
}
connectionhub.Close();
connection.Close();
}
Edit: removed offending parentheses.
Without changing any of your C# code, it may be possible to get what you want by changing the SQL query from an INNER JOIN query to a CROSS JOIN query.
Some caveats regarding this approach though:
If you include a WHERE clause, the query will act as an INNER JOIN.
Cross joins can be significantly slower, as the query is looking to make all possible combinations. With only 51 (3 * 17) combinations available that will not be a significant issue, but if you are looking to scale this to more clients and stocks, it will become increasingly worse performance wise
Related
I need to return all values from my table. How to write a code inside while?
var stringConnection = "Data Source = X; User Id = X; Password = X";
var sql = "SELECT * FROM TABLE";
OracleConnection _oracleConnection = new OracleConnection(stringConnection);
_oracleConnection.Open();
OracleCommand cmd = new OracleCommand(sql, _oracleConnection);
var dr = cmd.ExecuteReader();
var list = new List<dynamic>();
while(dr.Read())
{
// my doubt is here
}
return list;
var stringConnection = "Data Source = X; User Id = X; Password = X";
var sql = "SELECT * FROM TABLE";
OracleConnection _oracleConnection = new OracleConnection(stringConnection);
_oracleConnection.Open();
OracleCommand cmd = new OracleCommand(sql, _oracleConnection);
var dr = cmd.ExecuteReader();
var list = new List<dynamic>();
while(dr.Read())
{
// **** read column name data from table ****
string Id = (string)dr["Id"];
string company = (string)dr["company"];
string city = (string)dr["City"];
var objItem = new { Id = Id, company = company, city = "city" };
list.Add(objItem);
}
return list;
You have several options. 1 - load DataSet from OracleDataReader. There you will have all your data.
2 - you can still use select *... but you need a model. Then create List<SomeModel> instead of List<dynamic> with
while (reader.Read())
{
model.Property = reader["columnName"]; // will need convert type and take care of DB null. Can use existing extnsions
. . . .
}
3 - For arbitrary number of columns use OracleDataReader.FieldCount and some storage like List<object[]>
var data = new List<object[]>();
var fCnt = reader.FieldCount;
while (reader.Read())
{
var arr = new Object[fCnt];
for(int i = 0; i < fCnt; i++)
arr[i] = reader[i];
data.Add(arr);
}
The unfortunate part with #3 is that in the end you can get jagged array and not 2-dimentional one but you now have enough info to convert it. But I don't remember when I needed to do #3. So think about #1 and #2
And one more thing - absolutely no need for dynamic here. Stay away.
I want the code to do something if the thing its looking for doesn't exist in the DB. This is what I am working with currently:
const string cs = #"Data Source= ..\..\..\database.sqlite3";
await using var con = new SQLiteConnection(cs);
con.Open();
await using var cmd = new SQLiteCommand(con);
member ??= ctx.Member;
cmd.CommandText = #"SELECT iq FROM users WHERE id = $user_id";
cmd.Parameters.AddWithValue("$user_id", member.Id);
var r = cmd.ExecuteReader();
while (r.Read())
{
if (r["iq"] == null)
{
var random = new Random();
var iq = random.Next(1, 200);
await cmd.DisposeAsync();
cmd.CommandText = "INSERT INTO users(id, iq) VALUES($member_id, $id)";
cmd.Parameters.AddWithValue("$iq", iq);
cmd.Parameters.AddWithValue("$member_id", member.Id);
cmd.ExecuteNonQuery();
var embed = new DiscordEmbedBuilder
{
Title = $"IQ of {member.Username} is {iq} :brain:",
Color = DiscordColor.Cyan
};
await ctx.Channel.SendMessageAsync(embed);
}
else
{
var iqFinal = r["iq"];
var embed = new DiscordEmbedBuilder
{
Title = $"IQ of {member.Username} is {iqFinal} :brain:",
Color = DiscordColor.Cyan
};
await ctx.Channel.SendMessageAsync(embed);
}
}
I really don't know how do make that happen, I've tried try catch blocks but they didn't seem to work either. How can I do this?
I assume that id is the primary key of the table, so you don't expect more than 1 rows from the statement:
SELECT iq FROM users WHERE id = $user_id
The problem with this statement is that it may not return any rows if $user_id does not exist in the table, so in this case r.Read() will return false and the code inside the while loop will never be executed.
One way to do what you want is to use aggregation:
SELECT MAX(iq) AS iq FROM users WHERE id = $user_id
which always returns a row: either the row with the iq where id = $user_id or null if $user_id does not exist in the table.
Also you should change the while loop to just:
if (r.Read()) {
.....................
}
or better just:
r.Read();
because the aggregation query is guaranteed that will return exactly 1 row.
I'm making a windows form application that manipulate data from SQL server. I'm trying to get column type and put it in the table so it can be something like that(Label{columnName}{columnType} Textbox).
The query is:
SELECT DATA_TYPE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'comboBox1.SelectedItem'
AND COLUMN_NAME = '{labels[i].Text}'
I need only to understand how can I put that query in a value with the result and add it to my tableLayout.
Trying that now, but it's not executed
using (form1.conn = new SqlConnection($"Server = {form1.ServerBox.Text }; Database = { form1.DBBox.Text}; Trusted_Connection = True"))
{
form1.conn.Open();
using (cmd = new SqlCommand(getSqlTypes, form1.conn))
{
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
labels[i] = new Label();
labels[i].Text = (string)reader["TABLE_NAME"];
tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
tableLayoutPanel.SetCellPosition(labels[i], new TableLayoutPanelCellPosition(2, k++));
}
}
}
form1.conn.Close();
}
Happened with the following code:
SqlDataAdapter sqladapter = new SqlDataAdapter($"{getSqlTypes}", form1.conn = new SqlConnection($"Server = {form1.ServerBox.Text }; Database = { form1.DBBox.Text}; Trusted_Connection = True"));
DataSet dt = new DataSet();
sqladapter.Fill(dt);
labels[i] = new Label();
labels[i].Text = dt.Tables[0].Rows[0][0].ToString();
tableLayoutPanel.SetCellPosition(labels[i], new TableLayoutPanelCellPosition(2, k++));
tableLayoutPanel.Controls.Add(labels[i]);
getSqlTypes = $"SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '{comboBox1.SelectedItem}' AND COLUMN_NAME = ";
I think my code is correct but why error syntax near 'po_no' check my code please. What is the problem with my code with this kind of error? Do I need to JOIN or two queries? I just want to display the two table using inner join
try
{
if (cb_po_search.Text == "")
{
MessageBox.Show("Please Enter to Search!");
}
else
{
string strPRSconn = ConfigurationManager.ConnectionStrings["POSdb"].ConnectionString;
SqlConnection sc = new SqlConnection(strPRSconn);
sc.Open();
string strQry = "SELECT dbo.POMain.po_no, dbo.POMain.issuing_month, dbo.POMain.supplier, dbo.POMain.model, dbo.POMain.category, dbo.POMain.req_number, dbo.POMain.shipment, dbo.POMain.production_month, dbo.POMain.req_time_arrival, dbo.POMain.req_department, dbo.POMain.lead_time, dbo.POMain.order_desc, dbo.POMain.date_emailed, dbo.POMain.date_confirmed, dbo.POMain.date_recieved, dbo.POMain.assumed_arrival, dbo.Shipping.invoice, dbo.Shipping.loading_date, dbo.Shipping.etd, dbo.Shipping.eta_manila, dbo.Shipping.eta_tstech, dbo.Shipping.ata_tstech, dbo.Shipping.shipping_status, dbo.Shipping.remarks FROM dbo.POMain INNER JOIN dbo.Shipping ON dbo.POMain.po_no = dbo.Shipping.po_noWHERE po_no= '" + cb_po_search.Text + "'";
SqlCommand scmd = new SqlCommand(strQry, sc);
SqlDataAdapter da = new SqlDataAdapter(strQry, sc);
DataTable dt = new DataTable();
SqlDataReader dr = scmd.ExecuteReader();
while (dr.Read())
{
//purchase order
tb_ponumber2.Text = (dr["po_no"].ToString());
tb_reqnumber2.Text = (dr["req_number"].ToString());
cb_supplier2.Text = (dr["supplier"].ToString());
cb_model2.Text = (dr["model"].ToString());
cb_category2.Text = (dr["category"].ToString());
cb_shipment2.Text = (dr["shipment"].ToString());
ta_description2.Text = (dr["order_desc"].ToString());
tb_leadtime2.Text = (dr["lead_time"].ToString());
tb_request2.Text = (dr["req_department"].ToString());
dt_time_arrival2.Value = DateTime.Parse(dr["req_time_arrival"].ToString());
dt_arrival2.Value = DateTime.Parse(dr["assumed_arrival"].ToString());
dt_confirmed2.Value = DateTime.Parse(dr["date_confirmed"].ToString());
dt_email2.Value = DateTime.Parse(dr["date_emailed"].ToString());
dt_production_month2.Value = DateTime.Parse(dr["production_month"].ToString());
dt_recieve2.Value = DateTime.Parse(dr["date_recieved"].ToString());
dt_issuing_month2.Value = DateTime.Parse(dr["issuing_month"].ToString());
}
sc.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
Your code is asking for an SQL Injection, use parametized queries instead with SqlParameter class.
Edit. Your query have a missing equals sign at the end. Things that woudn't happen using parametized queries ;-)
http://www.csharp-station.com/Tutorial/AdoDotNet/lesson06
I was given a query, originally done in ColdFusion, but I am having difficulties with the translation to a Winform use. I have a textbox that contains a concatenated string of other textboxes to make a case number. The purpose of this is to check for a record that might have been a transfer. In the first query, it is based on column caa443400048 either having something or being NULL. How would I incorporate that into a conditional statement for checking?
<cfquery name="q_transfer" datasource=#DSN#>
SELECT caa443400048
FROM caa44340
WHERE caa44340041 = '#SearchCaseNo#'
</cfquery>
<CFSET TransferCaseNo = "">
<CFSET TransferFlag = 'N'>
<CFIF #q_transfer.caa443400048# NEQ "">
<cfquery name="q_newcaseno" datasource=#DSN# >
SELECT caa44340041
FROM caa44340
WHERE caa443400018 = '#q_transfer.caa443400048#'
</cfquery>
<CFSET TransferFlag = 'Y'>
<CFSET TransferCaseNo = #SearchCaseNo#>
<CFSET SearchCaseNo = #q_newcaseno.caa44340041#>
</cfif>
Here is the C# code I am currently using:
string sql = "select COUNT (caa443400048) FROM caa44340 WHERE caa44340041 = ? ";
OdbcConnection con = new OdbcConnection("Dsn=XXXXX; User ID=XXXXX; Password=XXXXX");
con.Open();
OdbcCommand cmd = new OdbcCommand(sql, con);
cmd.Parameters.AddWithValue("caa44340041", txtCustomCaseNumber.Text);
int count = Convert.ToInt32(cmd.ExecuteScalar());
con.Close();
if (count != 0)
{
MessageBox.Show("This is a transfer");
}
else
{
MessageBox.Show("This is not a transfer");
}
I'm not 100%, but maybe this may help:
var TransferFlag = "N";
var SearchCaseNo = "";
var q_transfer = "";
var q_newcaseno = "";
using (var con = new OdbcConnection("Dsn=XXXXX; User ID=XXXXX; Password=XXXXX"))
{
con.Open();
using (var cmd = new OdbcCommand("SELECT caa443400048 FROM caa44340 WHERE caa44340041 = ?", con))
{
cmd.Parameters.AddWithValue("#var", txtCustomCaseNumber.Text);
q_transfer = (string)cmd.ExecuteScalar();
}
if (!string.IsNullOrEmpty(q_transfer))
{
using (var cmd = new OdbcCommand("SELECT caa44340041 FROM caa44340 WHERE caa443400018 = ?", con))
{
cmd.Parameters.AddWithValue("#var", q_transfer);
q_newcaseno = (string)cmd.ExecuteScalar();
}
TransferFlag = "Y";
SearchCaseNo = q_newcaseno;
MessageBox.Show("This is a transfer");
}
else
MessageBox.Show("This is not a transfer");
}