Check if column exists and then do selects from table using C# - c#

please can anyone point me in the right direction. I want to check if the column exists, if so do this select else do another select
select case
when exists (
SELECT *
FROM Sys.columns c
WHERE c.[object_id] = OBJECT_ID('dbo.Municipality')
AND c.name = 'AmountTypeLabel'
)
then 1
else 0
end
This Checks if column exists and then return a 0 or a 1 but there is no column name so i can't check it in C#
This is what i have tried in C# but as i said before there is no column name
DataTable DT;
string SQL = "";
try
{
SQL = "select case " +
" when exists( " +
" SELECT 1 " +
" FROM Sys.columns c " +
" WHERE c.[object_id] = OBJECT_ID('dbo.Municipality')" +
" AND c.name = 'AmountTypeLabel'" +
")" +
" then 1 " +
" else 0 " +
" end ";
DT = Conn.ExecuteDT(SQL);
}
catch (Exception ex)
{
throw new Exception("Unable to get Tables", ex);
}
return DT;
}

With existing code you can fetch the value by using the below and use it in another function:
if(DT.Rows[0][0].ToString() == "1")
//Do Something
OR you could to use SQL Alias in your SQL query like below :
" end AS ColumnExists";
and then you can refer this in your other function. Sample snippet below -
if(DT.Rows[0]["ColumnExists"].ToString() == "1")
//Do Something
On a side note if the requirement is to fetch only the 1 or 0 from SQL server then use the ExecuteScalar as mentioned by Matteo1010 in comments.
var columnExists = cmd.ExecuteScalar();
if(columnExists.ToString() == "1")
//Do Something

Related

Understanding details on Dapper objects and splits and maps in C# and .NET Core

I am looking at a new project and have a bug that needs fixing but have never used Dapper every (only read about it as I believe this site uses it). I am trying to understand a couple of things in the following code block below. The entire code block is listed initially for readability and then the questions are broken down below that with snippets from the code.
Code block:
_sql = "SELECT p.*, " +
"s.SupplierId AS 'SplitOnSupplierId', s.*, " +
"pd.ProductId AS 'SplitOnProductId', pd.* " +
"FROM Parts p " +
"JOIN Supplier s ON s.SupplierId = p.SupplierId " +
"JOIN Productss pd ON pd.ProductId = " + productId + " " +
"WHERE p.SupplierId = '" + supplierId + "' " +
"AND p.PartModel = '" + partModel + "'";
var result = new List<Parts>();
try
{
using (_myDb = DapperConnect.GetOpenConnection())
{
result = _myDb.Query<Parts, Supplier, Product, Parts>(_sql,
commandType: CommandType.Text,
map: (p, s, pd) =>
{
p.Supplier = s;
p.Product = pd;
return p;
},
splitOn: "SplitOnSupplierId,SplitOnProductId").ToList();
return result.Count == 0 ? null : result[0];
};
}
catch
{
return null;
}
Code with fragments and questions:
The _spl query just gets all the data needed to make the objects in the mapping section below.
I need to go through this an understand the nature of what is needed, so that question can be ignored.
_sql = "SELECT p.*, " +
"s.SupplierId AS 'SplitOnSupplierId', s.*, " +
"pd.ProductId AS 'SplitOnProductId', pd.* " +
"FROM Parts p " +
"JOIN Supplier s ON s.SupplierId = p.SupplierId " +
"JOIN Productss pd ON pd.ProductId = " + productId + " " +
"WHERE p.SupplierId = '" + supplierId + "' " +
"AND p.PartModel = '" + partModel + "'";
var result = new List<Parts>();
try
{
using (_myDb = DapperConnect.GetOpenConnection())
{
I do not understand why Parts is in this list twice and in general terms what does this line do?
result = _myDb.Query<Parts, Supplier, Product, Parts>(
_sql,
commandType: CommandType.Text,
I think I see that the query above is putting all the results from _sql into a list of Parts objects
with their relationships to Supplier and Product?
map: (p, s, pd) =>
{
p.Supplier = s;
p.Product = pd;
return p;
},
I am not quite sure what or how this line below works.
splitOn: "SplitOnSupplierId,SplitOnProductId").ToList();
return result.Count == 0 ? null : result[0];
};
}
catch
{
return null;
}
As I said before I have never used Dapper in any sort of way and this is the first day I am truly reading about it. Any help is
greatly appreciated.
Dapper doesn't know about your database relations, so you need to tell it how to map the data.
The data comes as a set of rows and the mapping is saying what to do with each row. The generic query (Q2) needs to know what parts to split the row into and which type is should return. In your case it says "split into Parts, Supplier and Product and return Parts". That's why Parts is there twice.
The mapping part in Q3 gets your three objects p, s and d and establishes the relations. This should return something of type Parts, and so it does. The last bit (Q4) is about where to cut the data row into the three objects and it mentions two data columns that should be used as separators. So everything before SplitOnSupplierId is Parts, the next bit is Supplier until you reach SplitOnProductId and the rest is Product.
Your code is vulnerable to SQL Injection. You should use parameters instead of building the SQL query as text. It could also increase performance. Your code would look something like this:
_sql = #"SELECT p.*, s.SupplierId AS 'SplitOnSupplierId', s.*,
pd.ProductId AS 'SplitOnProductId', pd.*
FROM Parts p JOIN Supplier s ON s.SupplierId = p.SupplierId
JOIN Productss pd ON pd.ProductId = p.ProductId
WHERE p.SupplierId = #SupplierId
AND p.ProductId = #ProductId
AND p.PartModel = #PartModel";
try
{
using (_myDb = DapperConnect.GetOpenConnection())
{
var result = _myDb.Query<Parts, Supplier, Product, Parts>(_sql,
commandType: CommandType.Text,
map: (p, s, pd) =>
{
p.Supplier = s;
p.Product = pd;
return p;
},
new {SupplierId = supplierId , ProductId = productId , PartModel = partModel },
splitOn: "SplitOnSupplierId,SplitOnProductId").ToList();
return result.Count == 0 ? null : result[0];
};
}
catch
{
return null;
}
You could also use QueryFirstOrDefault or QuerySingleOrDefault to have only one result returned.

how to join two tables in sql and showing the results event A then all attendees, Event B and showing all the attendees, etc

Good Afternoon All,
I am creating an admin page that shows a list of events and those who volunteered to help. I have one table for events and another for those who are volunteer.
I stored the eventID into the volunteer's table and am able to join them, but when i join them I get a new row for each volunteer which also shows the event name again.
I would like to display the event name and underneath the event name show the volunteers.
ex.
event A
Volunteer 1
volunteer 2
volunteer 3
event B
Volunteer 1
volunteer 2
Can anyone point me in the right direction?
public string volunteers(){
SqlCommand cmd = new SqlCommand(#"SELECT* FROM fundraiser_youth
LEFT JOIN
fundrasier_helpers ON fundraiser_youth.id = fundrasier_helpers.eventID
ORDER BY reportTime;", con);
con.Open();
SqlDataReader reader;
reader = cmd.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
DateTime reportTime = Convert.ToDateTime(reader[1]);
DateTime gateTime = Convert.ToDateTime(reader[2]);
DateTime gameTime = Convert.ToDateTime(reader[3]);
VOLUNTEER.Append("<div class='col-md-4'>");
VOLUNTEER.Append("<div class='well well-lg'>");
VOLUNTEER.Append("<form action='register/default.aspx' method='POST'>");
VOLUNTEER.Append("<h4>" + reportTime.DayOfWeek + " " + reportTime.Month + "/" + reportTime.Day + "/" + reportTime.Year + "</h4>");
VOLUNTEER.Append("<h5>" + reader[4].ToString() + " " + reader[7].ToString() + " " + reportTime.ToString("h:mm tt", CultureInfo.InvariantCulture) + "</h5>");
VOLUNTEER.Append("<ul>");
VOLUNTEER.Append("<li>" + reader[10].ToString() + " " + reader[11].ToString() + "</li>");
VOLUNTEER.Append("</ul>");
VOLUNTEER.Append("<input type=hidden name='id' value='" + reader[8].ToString() + "' />");
VOLUNTEER.Append("<span style='text-align:right; margin-top:20px;'><input type='submit' value='Register' class='btn btn-info' /></span>");
VOLUNTEER.Append("</form>");
VOLUNTEER.Append("</div>");
VOLUNTEER.Append("</div>");
}
return VOLUNTEER.ToString();
}
return "no info provided";
}
The first aspect of your stated problem is the select list. Select * will return all columns of all joined tables in the query for each joined row. So, each of your helpers will have the fundraising event information as part of its row data.
One side note for maintenance: select * is a bad habit for "production code", especially if you're getting fields out of the result set by index (which you are), because if you add a field to fundraiser_youth, all the indexes representing fields from fundraiser_helpers will no longer line up with the result set being returned, and your UI and any validation logic on this field data will break. I recommend strongly that you either specify the list of desired columns explicitly, get them out of reader using the column names instead of index positions, or both.
Since you're digesting the results programmatically in C#, the easiest solution to your stated problem is to first change your ORDER BY clause so that rows are sorted by fundraiser_youth.id before anything else. Then, get the event information once on the first row, generate your event header and the first volunteer row in HTML, remember that event ID, and check it against the ID of subsequent rows as you iterate through the reader generating the rest of the volunteer HTML rows. As long as the event IDs match, ignore the event fields and only extract/display the helper fields. When they differ, the event has changed and you need to re-retrieve the event information for the next sub-header.
Here is how I ended up fixing my problem. May not be best option but it works, Thanks for everyone's input and in the production code I replaced the select * with the columns. I made a new function called (loadHelpers) and pass the id of the current Event to it. This function pulls all the volunteers who signed up to help.
public string volunteers()
{
SqlCommand cmd = new SqlCommand(#"SELECT * FROM fundraiser_youth WHERE reportTime >='" + DateTime.Now + "' ORDER BY reportTime" , con);
con.Open();
SqlDataReader reader;
try
{
reader = cmd.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
DateTime reportTime = Convert.ToDateTime(reader["reportTime"]);
DateTime gateTime = Convert.ToDateTime(reader["gateTime"]);
DateTime gameTime = Convert.ToDateTime(reader["gameTime"]);
events.Append("<div class='col-md-4'>");
events.Append("<div class='well well-lg'>");
events.Append("<form action='register/default.aspx' method='POST'>");
events.Append("<h4>" + reportTime.DayOfWeek + " " + reportTime.Month + "/" + reportTime.Day + "/" + reportTime.Year + "</h4>");
events.Append("<h5>" + reader["eventName"].ToString() + " " + reader["location"].ToString() + " " + reportTime.ToString("h:mm tt", CultureInfo.InvariantCulture) + "</h5>");
events.Append(loadHelpers(reader["id"].ToString()));
events.Append("<!--<span style='text-align:right; margin-top:20px;'><input type='submit' value='Edit' class='btn btn-info' /></span>-->");
events.Append("</form>");
events.Append("</div>");
events.Append("</div>");
}
return events.ToString();
}
return "no info provided";
}
catch (Exception e)
{
return "ERROR" + e;
}
}
public string loadHelpers(string id)
{
var cmd2 = new SqlCommand(#"SELECT * FROM fundrasier_helpers WHERE eventID='"+ id + "'" , con2);
con2.Open();
if (cmd2.ToString() != "")
{
SqlDataReader reader2;
StringBuilder helper = new StringBuilder();
helper.Append("<ul>");
try
{
reader2 = cmd2.ExecuteReader();
if (reader2.HasRows)
{
while (reader2.Read())
{
helper.Append("<li>" + reader2["firstName"] + " " + reader2["lastName"] + " " + reader2["phone"] + " " + reader2["shirtSize"] + "</li>");
}
}
reader2.Close();
}
catch (Exception e)
{
helper.Append("<li>No volunteers have signed up " + e + "</li>");
}
helper.Append("</ul>");
con2.Close();
return helper.ToString();
}
else
{
return "<ul><li>No volunteers have signed up</li></ul>";
}
}

Datatype mismatch in criteria expression.in a select query c# Access database

I am building a simple Point of Sale program and working on a "search invoice" button that allows up to 3 search criteria (InvoiceID , ClientName, and ClientID). These are the names of 3 of the columns in the table named "Invoicing".
InvoiceID is the key column of type Int32, ClientName is of type String, ClientID is of type Int32. ClientName and ClientID searches work perfect.
MY PROBLEM: If I include InvoiceID in the select query, I get the following error. And I have spent a few days trying to figure it out.
ERROR: Database Error: Datatype mismatch in criteria expression.
Can you more experienced programmers help me out? thank you!
String connectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data" + #" Source=TESTDB.accdb";
String tableName = "Invoicing";
String query = String.Format("select * from [{0}] where", tableName);
//ADD IN SEARCH CRITERIA
int filled = 0;
if (invoiceBox.Text != "") { query += " InvoiceID='" + invoiceBox.Text+"'"; filled += 1; }
/*if (DateCheckBox.Checked == true)
{
if (filled>=1) { query += " and DateNTime='" + monthCalendar1.SelectionStart.ToString() + "'"; filled += 1; }
else { query += " DateNTime='" + monthCalendar1.SelectionStart.ToString()+ "'"; filled += 1; }
}
* */
if (ClientNameBox.Text != "") //Doesnot work
{
if (filled >= 1) { query += " and Client='" + ClientNameBox.Text + "'"; filled += 1; }
else { query += " Client='" + ClientNameBox.Text + "'"; filled += 1; }
}
if (ClientIDBox.Text != "") //THIS search criteria works!!!!
{
if (filled >= 1) { query += " and ClientID='" + ClientIDBox.Text + "'"; filled += 1; }
else { query += " ClientID='" + ClientIDBox.Text + "'"; filled += 1; }
}
//CHECK IF SEARCH CRITERIA ARE PRESENT
if (filled < 1) { MessageBox.Show("At least One Search criteria above is required"); return; }
DataSet dsInvoicing = new DataSet();
OleDbConnection conn = new OleDbConnection(connectionString);
try
{
//Open Database Connection
conn.Open();
OleDbDataAdapter daInvoicing = new OleDbDataAdapter(query, conn);
//Fill the DataSet
daInvoicing.Fill(dsInvoicing, tableName);
//MessageBox.Show("dsInventory has "+dsInventory.Tables[0].Rows.Count+" search results");
conn.Close();
this.dataGridView1.DataSource = dsInvoicing.Tables[0];
}
catch (OleDbException exp){ MessageBox.Show("Database Error: " + exp.Message.ToString());}
Need more information? I will post up more if I haven't provided enough.
DATABASE INFORMATION or other.
Thank you very much to all programmers.
Looks like the data type of InvoiceID in your database is some numeric kind. While in query you are treating it as string. Try not to wrap InvoiceID value in single quotes.

all_ind_expressions view of Oracle

I'm trying to execute the below query through OracleDataReader in .NET but when I try to read the value of the column_expressions column, I always get an empty string.
SELECT ic.column_name,
ie.column_expression
FROM all_ind_columns ic
LEFT JOIN all_ind_expressions ie
ON ie.index_owner = ic.index_owner
AND ie.index_name = ic.index_name
AND ie.column_position = ic.column_position
WHERE ic.index_owner = 'owner_name'
AND ic.index_name = 'index_name'
I realized that the datatype of the column id is LONG but I'm not sure if that's the reason. Is there a way I can read the actual value of the column?
When I execute the same query through Oracle SQL developer, I can see the value.
To be able to read a column that is of LONG data type the InitialLONGFetchSize property of OracleCommand has to be set to a none zero(zero by default) value:
Unfortunately you did not provide your .NET code, so I'll give you a C# + ODP.NET unmanaged driver example:
Set-up:
create table t1(
col1 varchar2(11)
);
create index FBI on t1(upper(col1));
table T1 created.
index FBI created.
C# code:
string oraConnectionString = "Data source=nkpdb;User id=hr;password=password;";
OracleConnection oraConnection = new OracleConnection(oraConnectionString);
oraConnection.Open();
/* Would be better to put this in a stored procedure */
string sqlQuery = "select ic.column_name " +
" , ie.column_expression " +
" from all_ind_columns ic " +
" left join all_ind_expressions ie " +
" on ie.index_owner = ic.index_owner " +
" and ie.index_name = ic.index_name " +
" and ie.column_position = ic.column_position " +
" where ic.index_owner = :INDOwner " +
" and ic.index_name = :INDName" ;
OracleCommand oraCmd = new OracleCommand(sqlQuery, oraConnection);
OracleParameter indOwner = new OracleParameter("INDOwner",
OracleDbType.Varchar2);
OracleParameter indName = new OracleParameter("INDName",
OracleDbType.Varchar2);
indOwner.Value = "HR";
indName.Value = "FBI";
oraCmd.Parameters.Add(indOwner);
oraCmd.Parameters.Add(indName);
/* set up initial amount of data that the OracleDataReader
* fetches for LONG column */
oraCmd.InitialLONGFetchSize = 1000; /* set initial size */
OracleDataReader oraDataReader = oraCmd.ExecuteReader();
if (oraDataReader.HasRows)
{
while (oraDataReader.Read())
{
Console.WriteLine(oraDataReader.GetString(
oraDataReader.GetOrdinal("column_expression")));
}
}
Result:
By default the InitialLONGFetchSize property is set to 0. That's the reason why you are getting an empty string. So you either need to set this property to a value greater than zero or set it to -1 to fetch an entire LONG column.
Here 's another simple solution.
1 - Create this function
create or replace function Get_Text
(sINDEX_NAME in VARCHAR2, sIndex_owner in VARCHAR2, sColumn_position in VARCHAR2)
return varchar2
is
Long_to_Varchar varchar(32767);
begin
select COLUMN_EXPRESSION into Long_to_Varchar
from SYS.all_ind_expressions
where INDEX_NAME = sINDEX_NAME and Index_owner=sIndex_owner and Column_position=sColumn_position;
return long_to_varchar;
exception
when others then
return 'Error occurred';
end;
2 - Use this SQL
select ic.index_name,
ic.column_name,
GET_TEXT(Ie.INDEX_NAME,Ie.Index_owner,ie.Column_position )
from all_ind_columns ic
left join all_ind_expressions ie
on ie.index_owner = ic.index_owner
and ie.index_name = ic.index_name
and ie.column_position = ic.column_position
WHERE ic.index_owner = 'owner_name'
AND ic.index_name = 'index_name'

Insert a new record in access using oledb

Can I add a new record into access database which has 15 columns? It's very unconvinient for me to using this sql:
insert into Account(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11,col12,col13,col14,col15) Values(val1,val2,val3,val4,val5,val6,val7,val8,val9,val10,val11,val12,val13,val14,val15)
There are 2 List consist columns name (name) and values (info). Example:
name[1]="col1";
info[1]="val1";
Is the ordinary of columns name important? Can I use this Sql:
insert into Account(col1) Values(val1)
After that I use an "update" sql and a "for-loop" to set values?
I also get an error:
The changes you requested to the table were not successful because they would create duplicate values in the index, primary key, or relationship. Change the data in the field or fields that contain duplicate data, remove the index, or redefine the index to permit duplicate entries and try again.
Thank you so much. :)
Do one insert before for loop and update in the for loop.
A sample code is given below.
string Query = "insert into Account(col1) Values(val1)";
// execute it
for(int i=1;i<name.count -1;i++)
{
Query = "Update Account set " + name[i] + " = " + info[i] + " where col1 = val1";
// execute
}
Code not tested.
public static void insert(String[] name ,String[] info)
{
String Names = "";
String Cols = "";
for(int i=0;i < name.Length;i++)
{
Names += (Names == "" ? "" : ", ") + name[i];
Cols += (Cols == "" ? "" : ", ") + "'" + info[i] + "'";
}
String Query = "insert into Account (" + Names + ") Values (" + Cols + ")";
Console.WriteLine(Query);
}
Code not tested and note that I added single quotes for values assuming that all values are string type.

Categories