I am begginer with ADO.NET , I try update table with DataSet.
O client side I have dataset with one table. I send this dataset on service side (it is ASP.NET Web Service).
On Service side I try update table in database, but it dont 't work.
public bool Update(DataSet ds)
{
SqlConnection conn = null;
SqlDataAdapter da = null;
SqlCommand cmd = null;
try
{
string sql = "UPDATE * FROM Tab1";
string connStr = WebConfigurationManager.ConnectionStrings["Employees"].ConnectionString;
conn = new SqlConnection(connStr);
conn.Open();
cmd=new SqlCommand(sql,conn);
da = new SqlDataAdapter(sql, conn);
da.UpdateCommand = cmd;
da.Update(ds.Tables[0]);
return true;
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (conn != null)
conn.Close();
if (da != null)
da.Dispose();
}
}
Where can be problem?
It is better to look how really ADO.Net dataset works.
http://support.microsoft.com/kb/308507
Related
I have problem when using ADO.NET connection for PostgreSQL. I have tried this query using PSQLODBC driver 12.000.000 both ANSI and Unicode. I use PostgreSQL v.9.5. I notice the column name has "_" in its name.
When I use the Select query, the connection successfully execute it. The query return variables as I want.
using (OdbcConnection conn = (OdbcConnection)Dts.Connections["XXX"].AcquireConnection(Dts.Transaction))
{
try
{
if (conn.State != ConnectionState.Open)
{
conn.Open();
}
}
catch (Exception e)
{
String err = e.Message.ToString();
Console.WriteLine(err);
}
try
{
OdbcCommand cmd = new OdbcCommand();
cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT XX FROM <<table>> where <<params>>";
...
OdbcDataReader rdd = cmd.ExecuteReader();
while (rdd.Read())
{
<<read operation here>>;
}
conn.Close();
}
catch (Exception ers)
{
<<catch operation here>>;
}
}
But when I use Insert query, it failed to check the column name, even the column are exist in my PostgreSQL tables:
using (OdbcConnection conn2 = (OdbcConnection)Dts.Connections["OJK_REPORTING_DEV"].AcquireConnection(Dts.Transaction))
{
try
{
if (conn2.State != ConnectionState.Open)
{
conn2.Open();
}
}
catch (Exception e)
{
string x = e.Message.ToString();
}
try
{
OdbcCommand cmd = new OdbcCommand();
cmd.Connection = conn2;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "INSERT INTO <<table>>(<<column>>)VALUES(<<params>>)";
<<cmd.Parameters.AddWithValue here>>;
cmd.ExecuteNonQuery();
conn2.Close();
}
catch (Exception e)
{
<<exception catch here>>;
}
}
When I debug this line, I get this error:
ERROR[42703] ERROR: column <> not found, error while executing the query
Right, after several research, I've got an answer. Since i use PostgreSQL ODBC, the query parameters are not using #<name> inside the query, but using ?, so you need to formulate the query like
INSERT INTO <TABLE_NAME> (<COLUMNS>) VALUE ?
and call the parameters
cmd.AddWithValue("#<name>",<value>)
I have many rpt files. I want to change the query for each report using C#. There are several ways to do this changes.
First way:
private void button_Test_Click(object sender, EventArgs e)
{
ReportDocument rptDoc = new ReportDocument();
rptDoc.Load("D:\\Temp_01\\Report1_Test.rpt");
rptDoc.SetDatabaseLogon("User", "Password", "ServName", "DBName");
CrystalDecisions.Shared.ConnectionInfo ConnInf;
ConnInf = rptDoc.Database.Tables[0].LogOnInfo.ConnectionInfo;
String strSQLQuery = "SELECT TOP(123) * FROM sys.all_objects";
String strTableName = rptDoc.Database.Tables[0].Name;
try
{
rptDoc.SetSQLCommandTable(ConnInf, strTableName, strSQLQuery);
rptDoc.VerifyDatabase();
}
catch (Exception ex) { rptDoc.Close(); }
rptDoc.SaveAs("D:\\Temp_02\\Report2_Test.rpt");
rptDoc.Close();
}
It is not the best way. The method SetSQLCommand does not work when the query has any parameters. Even if you set value for each parameter, SetSQLCommand does not work. The example with a parameter which does not work:
private void button_Test_Click(object sender, EventArgs e)
{
ReportDocument rptDoc = new ReportDocument();
rptDoc.Load("D:\\Temp_01\\Report1_Test.rpt");
rptDoc.SetDatabaseLogon("User", "Password", "ServName", "DBName");
CrystalDecisions.Shared.ConnectionInfo ConnInf;
ConnInf = rptDoc.Database.Tables[0].LogOnInfo.ConnectionInfo;
String strSQLQuery = "SELECT TOP(1) * FROM sys.all_objects WHERE name = {?strName}";
String strTableName = rptDoc.Database.Tables[0].Name;
try
{
rptDoc.SetParameterValue("strName", "Text");
rptDoc.SetSQLCommandTable(ConnInf, strTableName, strSQLQuery);
rptDoc.VerifyDatabase();
}
catch (Exception ex) { rptDoc.Close(); }
rptDoc.SaveAs("D:\\Temp_02\\Report2_Test.rpt");
rptDoc.Close();
}
It returns an error. This method does not work with parameters!
Second way:
private void button_Test_Click(object sender, EventArgs e)
{
ReportDocument rptDoc = new ReportDocument();
rptDoc.Load("D:\\Temp_01\\Report1_Test.rpt");
rptDoc.SetDatabaseLogon("User", "Password", "ServName", "DBName");
ISCDReportClientDocument rcd = null;
rcd = rptDoc.ReportClientDocument as ISCDReportClientDocument;
CommandTable rTblOld;
CommandTable rTblNew;
rTblOld = rcd.Database.Tables[0] as CommandTable;
rTblNew = rcd.Database.Tables[0].Clone(true) as CommandTable;
rTblNew.CommandText = "SELECT TOP(1) * FROM sys.all_objects";
try
{
rcd.DatabaseController.SetTableLocationEx(rTblOld, rTblNew);
rcd.VerifyDatabase();
}
catch (Exception ex) { rcd.Close(); }
rcd.SaveAs(rcd.DisplayName, "D:\\Temp_02\\", 1);
rcd.Close();
}
This is also not the best way. The method SetLocalTableEx does a struct of the report is bad. After run SetLocalTableEx, attribute ConnectionInf.UserId have value NULL also the Name of connection
After SetTableLocationEx:
rcd.DatabaseController.SetTableLocationEx(rTblOld, rTblNew);
String UserID;
UserID = rptDoc.Database.Tables[0].LogOnInfo.ConnectionInfo.UserID;
if (UserID == null) MessageBox.Show("UserID has NULL");
UserId has value NULL
Also, before run SetTableLocationEx, Connection Name is MSODBCSQL11
enter image description here
After run SetTableLocationEx, Connection Name is Command
enter image description here
So,
how do dynamic and correctly to change the query in CommandTable for Crystal Reports file?
Thanks,
Artem
You are using command in Crystal Report which is the best way when doing and displaying a data from database to crystal report but unfortunately you do it in Code Behind.
My Question is:
Why don't you do it in Command of Crystal Report itself?
see this link for more info.
I am using a stored procedure in my SQL Server database to take input of the data through the datatable. As I am using ASP.NET MVC now, I want to use Entity Framework instead of ado.net
public void BulkUpload(DataTable dt)
{
dt.TableName = "MainTable";
DataSet dataset = new DataSet();
DataTable dataTable = new DataTable();
try
{
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["conn"].ConnectionString))
{
conn.Open();
{
SqlCommand cmd = new SqlCommand("DatatableToDataBase", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#mode", SqlDbType.VarChar).Value = "MainTB";
cmd.Parameters.AddWithValue("#Details", SqlDbType.VarChar).Value = dt;
cmd.ExecuteNonQuery();
conn.Close();
}
}
}
catch (Exception)
{ }
}
It's very easy just add an entity datamodel to your program
connect to you model :
"entitymodel" context = this.CurrentDataSource;
And pass the stored procedure where you like .
Thats everything
Example:
[WebGet]
public List<callersW> GetCaller()
{
testCDREntities1 context = this.CurrentDataSource;
//sql parameters here
List<callersW> result = context.Database.SqlQuery<callersW>("StoredProcedure").ToList();
return result;
}
I want to configure Tomcat 8 with PostgreSQL
I added this in context.xml
<Resource name="jdbc/DefaultDB" auth="Container" type="javax.sql.DataSource"
username="postgres" password="qwerty"
url="jdbc:postgresql://localhost:5432/crm"
driverClassName="org.postgresql.Driver"
initialSize="5" maxWait="5000"
maxActive="120" maxIdle="5"
validationQuery="select 1"
poolPreparedStatements="true"/>
And I tried to run this Java code:
public String init()
{
String user_name = null;
try
{
Context ctx = new InitialContext();
if (ctx == null)
throw new Exception("Boom - No Context");
DataSource ds = (DataSource) ctx.lookup("jdbc/DefaultDB");
if (ds != null)
{
Connection conn = ds.getConnection();
if (conn != null)
{
Statement stmt = conn.createStatement();
ResultSet rst = stmt.executeQuery("select id, user_name from user where username = " + user);
if (rst.next())
{
user_name = rst.getString("user_name");
}
conn.close();
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
return user_name;
}
But for some reason after I added this code Tomcat is not starting. Do you have any idea where I'm wrong?
I get this in Tomcat log file:
28-Mar-2016 10:37:07.955 WARNING [localhost-startStop-1] org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory.getObjectInstance Name = DefaultDB Property maxActive is not used in DBCP2, use maxTotal instead. maxTotal default value is 8. You have set value of "120" for "maxActive" property, which is being ignored.
28-Mar-2016 10:37:07.956 WARNING [localhost-startStop-1] org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory.getObjectInstance Name = DefaultDB Property maxWait is not used in DBCP2 , use maxWaitMillis instead. maxWaitMillis default value is -1. You have set value of "5000" for "maxWait" property, which is being ignored.
javax.naming.NameNotFoundException: Name [jdbc/DefaultDB] is not bound in this Context. Unable to find [jdbc].
as #a_horse_with_no_name says, your lookup is wrong. your code must be like this:
public String init()
{
String user_name = null;
try
{
Context ctx = new InitialContext();
if (ctx == null)
throw new Exception("Boom - No Context");
Context envCtx = (Context) ctx.lookup("java:comp/env");
DataSource ds = (DataSource) envCtx.lookup("jdbc/DefaultDB");
if (ds != null)
{
Connection conn = ds.getConnection();
if (conn != null)
{
Statement stmt = conn.createStatement();
ResultSet rst = stmt.executeQuery("select id, user_name from user where username = " + user);
if (rst.next())
{
user_name = rst.getString("user_name");
}
conn.close();
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
return user_name;
}
I am developing a stand alone application, using sql server compact 3.5 sp2 which runs in process. No Database writes involved. Its purely a reporting application. Read many articles about reusing open db connections in case of sql compact(connection pooling) due to its different behavior from sql server.
Quoting the comments from a quiz opened by Erik Ejlskov Jensen Link, where its discussed an open early close late strategy for sql server compact databases. Based on this, with my limited experience I have implemented a not so complex Connection handling+Data access layer. Basically I am unsure if i am writing it in a recommended way. Please could any one point me in the right direction with rooms for improvement in this connection handling approach i have written?
The DbConnection class
public class FkDbConnection
{
private static SqlCeConnection conn;
private static DataTable table;
private static SqlCeCommand cmd;
~FkDbConnection() { conn = null; }
//This will be called when the main winform loads and connection will be open as long as the main form is open
public static string ConnectToDatabase()
{
try {
conn = new SqlCeConnection(ConfigurationManager.ConnectionStrings["Connstr"].ConnectionString);
if (conn.State == ConnectionState.Closed || conn.State == ConnectionState.Broken)
{
conn.Open();
}
return "Connected";
}
catch(SqlCeException e) { return e.Message; }
}
public static void Disconnect()
{
if (conn.State == ConnectionState.Open || conn.State == ConnectionState.Connecting || conn.State == ConnectionState.Fetching)
{
conn.Close();
conn.Dispose();
//conn = null; //does conn have to be set to null?
}
//else the connection might be already closed due to failure in opening it
else if (conn.State == ConnectionState.Closed) {
conn.Dispose();
//conn = null; //does conn have to be set to null?
}
}
/// <summary>
/// Generic Select DataAccess
/// </summary>
/// <param name="sql"> the sql query which needs to be executed by command object </param>
public static DataTable ExecuteSelectCommand(SqlCeCommand comm)
{
if (conn != null && conn.State == ConnectionState.Open)
{
#region block using datareader
using (table = new DataTable())
{
//using statement needed for reader? Its closed below
using (SqlCeDataReader reader = comm.ExecuteReader())
{
table.Load(reader);
reader.Close(); //is it needed?
}
}
#endregion
# region block using dataadpater
//I read DataReader is faster?
//using (SqlCeDataAdapter sda = new SqlCeDataAdapter(cmd))
//{
// using (table = new DataTable())
// {
// sda.Fill(table);
// }
//}
#endregion
//}
}
return table;
}
/// <summary>
/// Get Data
/// </summary>
/// <param name="selectedMPs"> string csv, generated from a list of selected posts(checkboxes) from the UI, which forms the field names used in SELECT </param>
public static DataTable GetDataPostsCars(string selectedMPs)
{
DataTable dt;
//i know this it not secure sql, but will be a separate question to pass column names to select as parameters
string sql = string.Format(
"SELECT " + selectedMPs + " "+
"FROM GdRateFixedPosts");
using (cmd = new SqlCeCommand(sql,conn))
{
cmd.CommandType = CommandType.Text;
//cmd.Parameters.Add("#fromDateTime",DbType.DateTime);
//cmd.Parameters.Add("#toDateTime",DbType.DateTime);
dt = ExecuteSelectCommand(cmd);
}
return dt;
}
}
The Main UI (Form) in which connection opened, for connection to be open through out. 2 other reporting forms are opened from here. Closing main form closes all, at which point connection is closed and disposed.
private void FrmMain_Load(object sender, EventArgs e)
{
string str = FkDbConnection.ConnectToDatabase();
statStDbConnection.Items[0].Text = str;
}
private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
{
FkDbConnection.Disconnect();
}
Comments, improvements on this connection class much appreciated. See my questions also inline code
Thank you.
Updated classes as per Erik's suggestion. with a correction on ExecuteSelectCommand() and an additional class which will instantiate command objs in "using" and pass data to the UI. I intent to add separate GetDataForFormX() methods since the dynamic sql for each form may differ. Hope this is ok?
Correction to Erik's code:
public static DataTable ExecuteSelectCommand(SqlCeCommand comm)
{
var table = new DataTable();
if (conn != null && conn.State == ConnectionState.Open)
{
comm.Connection = conn;
using (SqlCeDataReader reader = comm.ExecuteReader())
{
table.Load(reader);
}
}
return table;
}
New FkDataAccess class for passing Data to UI
public class FkDataAccess
{
public static DataTable GetDataPostsCars(string selectedMPs)
{
var table = new DataTable();
string sql = string.Format(
"SELECT " + selectedMPs + " " +
"FROM GdRateFixedPosts");
if (FkDbConnection.conn != null && FkDbConnection.conn.State == ConnectionState.Open)
{
using (SqlCeCommand cmd = new SqlCeCommand(sql, FkDbConnection.conn))
{
cmd.CommandType = CommandType.Text;
//cmd.Parameters.Add("#fromDateTime",DbType.DateTime);
table = FkDbConnection.ExecuteSelectCommand(cmd);
}
}
return table;
}
//public static DataTable GetDataXY(string selectedvals)
// and so on
}
Too much code in your data access class, makes it unreadable and hard to maintain
The SqlCeonnection object will be disposed when you close it (and when the app closes)
You cannot dispose the DataTable if you want to use it elsewhere, and it is an completely managed object anyway.
It is a good pattern to limit your classes to a single responsibility
public class FkDbConnection
{
private static SqlCeConnection conn;
~FkDbConnection() { conn = null; }
//This will be called when the main winform loads and connection will be open as long as the main form is open
public static void ConnectToDatabase()
{
// Handle failure to open in the caller
conn = new SqlCeConnection(ConfigurationManager.ConnectionStrings["Connstr"].ConnectionString);
conn.Open();
}
public static void Disconnect()
{
if (conn != null)
{
conn.Close();
}
}
public static DataTable ExecuteSelectCommand(SqlCeCommand comm)
{
var table = new DataTable();
if (conn != null && conn.State == ConnectionState.Open)
{
comm.Connection = conn;
using (SqlCeDataReader reader = comm.ExecuteReader())
{
table.Load(reader);
}
}
return table;
}
private void FrmMain_Load(object sender, EventArgs e)
{
try
{
FkDbConnection.ConnectToDatabase();
statStDbConnection.Items[0].Text = "Connected";
}
catch (Exception ex)
{
//Inform use that we canot proceed, what she can do to remedy, and exit
}
}
private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
{
FkDbConnection.Disconnect();
}