Could you please explain how to solve following problem? - npgsql

// Verbinndung zum SQL-Server aufbauen
NpgsqlConnection SqlConn = new NpgsqlConnection(Program.Data.Settings.SQL_Server_ConnectionString);
SqlConn.Open();
NpgsqlDataAdapter daSql = new NpgsqlDataAdapter("SELECT * FROM " + Program.Data.Tab_SinterPersonal, SqlConn);
NpgsqlCommandBuilder cmds = new NpgsqlCommandBuilder(daSql);
daSql.DeleteCommand = cmds.GetDeleteCommand();
daSql.InsertCommand = cmds.GetInsertCommand();
daSql.UpdateCommand = cmds.GetUpdateCommand();
daSql.Update(Program.Data.dsSql.Tables[Program.Data.Tab_SinterPersonal]);
//NpgsqlConnection.Commit();
SqlConn.Commit();
SqlConn.Close();
Error:
NpgsqlConnection does not contain a definition for Commit and no extension method Commit accepting a first argument of type NpgsqlConnection could be found (are you missing a using directive or an assembly reference?)

Commit isn't something that's done on a connection, it's done on a transaction. The code should look like the following:
using var conn = new NpgsqlConnection(Program.Data.Settings.SQL_Server_ConnectionString);
SqlConn.Open();
using var transaction = conn.BeginTransaction(); // Begin the transaction
var daSql = new NpgsqlDataAdapter("SELECT * FROM " + Program.Data.Tab_SinterPersonal, SqlConn);
var cmds = new NpgsqlCommandBuilder(daSql);
daSql.DeleteCommand = cmds.GetDeleteCommand();
daSql.InsertCommand = cmds.GetInsertCommand();
daSql.UpdateCommand = cmds.GetUpdateCommand();
daSql.Update(Program.Data.dsSql.Tables[Program.Data.Tab_SinterPersonal]);
transaction.Commit(); // Commit the transaction

Related

Conversion failed when converting from a character string to uniqueidentifier - Doesn't Rollback the transaction

The actual issue is not this - "Conversion failed when converting from a character string to uniqueidentifier" but the issue is that, the transaction doesn't get rolled back after you hit the issue.
My code here,
var connectionstring = "Server= ****; Database= ****; Integrated Security=True;";
var errorInformation = new List<string>();
using (SqlConnection objConn = new SqlConnection(connectionstring))
{
objConn.Open();
var objTrans = objConn.BeginTransaction(); // Begins here
var sql = $"insert into tblProject values('7', 'TestProject')";
SqlCommand insertCommand = new SqlCommand(sql, objConn, objTrans);
try
{
insertCommand.ExecuteNonQuery();
// ProjectID is a unique Identifier in database
SqlCommand cmd = new SqlCommand("SELECT * FROM SOMEOTHERTABLE WHERE PROJECTID=''", objConn, objTrans);
cmd.CommandType = CommandType.Text;
var dataTable = new DataTable("SomeTableName");
using (var adapter = new SqlDataAdapter(cmd))
{
var dt = adapter.Fill(dataTable); // Exception happens here
}
objTrans.Commit(); // Commit here
}
catch (Exception ex)
{
errorInformation.Add(ex.Message);
}
var sql1 = $"insert into tblProject values('8', 'TestProject')";
SqlCommand objCmd2 = new SqlCommand(sql1, objConn, objTrans);
objCmd2.ExecuteNonQuery();
if (errorInformation.Any())
{
objTrans.Rollback(); // Rollback here
}
}
The query that gets executed after the exception, using the same connection object will not rollback. This is a bug that Microsoft needs to look into. Otherwise their rollback feature is not reliable.
I would expect either my second insert command to fail or my rollback to be successful.

Linq To Sql Conversation In Wcf Service

Can you please provide an answer following sql query to linq . I have some knowledge about linq but i am confused about sql reader object ..
public AccountBalanceRequest AccountBalanceCheek(AccountBalanceRequest accountNumber)
{
using (SqlConnection conn = new SqlConnection(ConnectionString))
{
conn.Open();
var cmd = new SqlCommand("SELECT Account_Type,Account_Fees,Account_Balance,Over_Draft_Limit FROM Current_Account_Details WHERE Account_Number = '" + accountNumber.Account_Number + "'", conn);
cmd.CommandType = CommandType.Text;
var reader = cmd.ExecuteReader();
//read the result of the execute command.
while (reader.Read())
{
//assuming that your property is the same as your table schema. refer to your table schema Current_Account_Details
accountNumber.Account_Type = reader["Account_Type"].ToString();
accountNumber.Account_Fee = reader["Account_Fees"].ToString();
accountNumber.Account_Balance = reader["Account_Balance"].ToString();
accountNumber.Over_Draft_Limit = reader["Over_Draft_Limit"].ToString();
}
return accountNumber;
}
}
First you have to have DbContext which you must instantiate in using(usual practice):
using (DbContext db = new DbContext())
{
var results = (from ad in db.Current_Account_Details
where ad.Account_Number == accountNumber.Account_Number
select ad).ToList();
}
Make sure you have created the object data model from database.
I do not get the other part of your post but this would be the general idea of how to write Linq2Entities queries.

ADO.Net Get Inserted Row's ROW ID without designer wizard

I have a generic update function that takes a datatable, select query and uses this to update the database tables.It is working fine. I need to know is there a way to get back the inserted row's ID (identity field) by changing something in the below code.
Public Function UpdateDataTable_GetID(ByVal dt As DataTable, ByVal SQL As String, ByVal connString As String) As Integer
Dim conn As SqlConnection = Nothing
Dim cmd As SqlCommand
Dim adp As SqlDataAdapter = Nothing
Dim cmdBuilder As SqlCommandBuilder = Nothing
Dim UpdatedID As Integer
If SQL.Length <= 0 Then
Return False
End If
conn = New Data.SqlClient.SqlConnection(connString)
cmd = New Data.SqlClient.SqlCommand
cmd.Connection = conn
cmd.CommandText = SQL
cmd.CommandType = CommandType.Text
adp = New Data.SqlClient.SqlDataAdapter(cmd)
cmdBuilder = New Data.SqlClient.SqlCommandBuilder(adp)
Try
UpdatedID = Convert.ToInt32(adp.Update(dt)) ' What to do here to get the just inserted ID instead of number of records updated
adp.Dispose()
cmdBuilder.Dispose()
Return UpdatedID
Catch ex As System.Data.SqlClient.SqlException
' Closing connection
Return -1
Finally
End try
End function
I am aware of solutions wherein I can append "select scope_identity()" to the insert Command of data adapter's query using designer as well as editing the adapter's insertcommand text and then doing an ExecuteScalar(). I want to know if the generic adapter.Update() can be tweaked to get the inserted row's ID.
you can subscribe to this event in code like this : (C# I dont know VB)
adp.RowUpdated += adapter_RowUpdated;
and write the event yourself :
void adapter_RowUpdated(object sender, SqlRowUpdatedEventArgs e)
{
if (e.StatementType == StatementType.Insert)
{
object id = e.Command.Parameters["#ID"].Value;
e.Row[_identityFieldName] = id;
}
}
In this example the following has been added to the commandtext first :
SET #ID = SCOPE_IDENTITY()
and a private variable _identityFieldName has been filled.
Maybe this can help you.
EDIT: I noticed you also use an SqlCommandBuilder that makes things easier to add the Scope identity :
SqlCommand inserter = new SqlCommand();
inserter = cmdBuilder.GetInsertCommand(true).Clone();
inserter.CommandText += " SET #ID = SCOPE_IDENTITY()";
SqlParameter param = new SqlParameter();
param.Direction = ParameterDirection.Output;
param.Size = 4;
param.DbType = DbType.Int32;
param.ParameterName = "#ID";
inserter.Parameters.Add(param);
adp.InsertCommand = inserter;

c# error "Procedure 'spReturnLastRowNoteID' expects param '#noteid', which was not supplied." though I don't have input parameter in sp

ALTER PROCEDURE dbo.spReturnLastRowNoteID
(#noteid int OUTPUT)
AS
SET NOCOUNT ON
SELECT #noteid = NoteID
FROM NoteTable
WHERE NoteID = IDENT_CURRENT('NoteTable')
RETURN #noteid`
I don't think there is a problem in my sp and code but I'm not sure why i'm getting the error:
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
string sqlSearchCommand = "spReturnLastRowNoteID";
SqlCommand command = new SqlCommand(sqlSearchCommand, connection);
command.CommandType = CommandType.StoredProcedure;
SqlParameter noteid = command.Parameters.Add("#noteid", SqlDbType.Int);
noteid.Direction = ParameterDirection.ReturnValue;
command.ExecuteNonQuery();
lastnoteid = (int)command.Parameters["#noteid"].Value;
}
Try setting the parameters direction to Output.
noteid.Direction = ParameterDirection.Output;

Hitting "COM object that has been separated from its underlying RCW cannot be used" error

I am trying to write a Windows Form program on top of .NET 4.0 and accessing Microsoft Access Database. I can read and write with no problem but sometimes, I get this error:
COM object that has been separated from its underlying RCW cannot be used.
I tried to call this method (GetIDBasedonTeamName) with different inputs twice (on the same thread). The second time this is run, I got that error.
OleDbConnection conn = new OleDbConnection();
OleDbConnection mDB = new OleDbConnection();
OleDbCommand comm = new OleDbCommand();
OleDbCommand cmd;
OleDbDataReader dr;
public void OpenConnection(string name) // always call this method first in other methods to initialise connection
{
conn.ConnectionString = "Provider = Microsoft.Jet.OLEDB.4.0;Data source="
+ Application.StartupPath + "\\AppData\\" + name + ".mdb;";
conn.Open();
comm.Connection = conn;
comm.Parameters.Clear();
}
public string GetIDBasedonTeamName(string teamName)
{
string toReturn = "";
try
{
OpenConnection("form");
comm.CommandText = "Select ID from TeamDetails WHERE TeamName=#teamName";
comm.Parameters.AddWithValue("TeamName", teamName);
dr = comm.ExecuteReader();
while (dr.Read())
{
toReturn = dr[0].ToString();
}
}
catch (OleDbException e)
{
string err = e.Message.ToString();
return null;
}
finally
{
}
conn.Close();
dr.Close();
return toReturn;
}
Exception happened on dr = comm.ExecuteReader();.
The method that was calling this method have this 2 lines inside:
InfoConfig.team1id = Convert.ToInt32(dbm.GetIDBasedonTeamName(cbxTeam1.Text));
InfoConfig.team2id = Convert.ToInt32(dbm.GetIDBasedonTeamName(cbxTeam2.Text));
What could be the cause? I read around and they mentioned not to use different threads but it is the same thread here.
Thanks,
Guo Hong
Building on Martin Liversage's answer:
public string GetIDBasedonTeamName(string teamName) {
var connString = "Provider = Microsoft.Jet.OLEDB.4.0;Data source="
+ Application.StartupPath + "\\AppData\\" + name + ".mdb;";
using (var conn = new OleDbConnection(connString)) {
conn.Open();
using (var cmd = conn.CreateCommand()) {
cmd.CommandText="Select ID from TeamDetails WHERE TeamName = #teamName";
cmd.Parameters.AddWithValue("TeamName", teamName);
using (var rdr = cmd.ExecuteReader()) {
if (rdr.Read()) {
return (string)rdr["TeamName"];
}
//if no valid results will return null
}
}
}
}
Instead of creating the objects only once and storing them in fields in your class you should create, use and close the objects in your method. It is probably the Close you call in the end the method that releases the underlying COM objects giving you the exception on the second call.

Resources