How to use transactions in SMO.Server ConnectionContext - c#

Following examples 1, 2 I wrote the following:
using System;
using System.Data.SqlClient;
using System.IO;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Common;
namespace ScriptRunner
{
class Program
{
static void Main(string[] args)
{
var script = File.ReadAllText("Test.sql");
const string sqlConnectionString = #"Data Source=my\ds;
Initial Catalog=myic;
Connection Timeout=0;
Integrated Security=true";
SqlConnection connection = null;
Server server = null;
try
{
connection = new SqlConnection(sqlConnectionString);
server = new Server(new ServerConnection(connection));
connection.Open();
server.ConnectionContext.BeginTransaction();
server.ConnectionContext.ExecuteNonQuery(script);
server.ConnectionContext.CommitTransaction();
}
catch { server.ConnectionContext.RollBackTransaction(); }
finally { connection?.Dispose(); }
}
}
}
Everything works, except the transactions. The command just runs, if there is the error, everything before is already in database. How to make transactions work here?
[EDIT]
When I change the code to open the transaction at the SqlConnection level like this (here it's suggested, that there should be no difference):
SqlTransaction transaction = null;
try
{
connection = new SqlConnection(sqlConnectionString);
server = new Server(new ServerConnection(connection));
connection.Open();
transaction = connection.BeginTransaction();
server.ConnectionContext.ExecuteNonQuery(script);
transaction.Commit();
}
It throws InvalidOPexception : "ExecuteNonQuery requires the command to have a transaction when the connection assigned to the command is in a pending local transaction. The Transaction property of the command has not been initialized."
Yet I do not see a place where I can access the command object.

I've faced with same problem "ExecuteNonQuery requires the command to have a transaction...".
It seems that if perform begin/commit transaction for ServerConnection, not for SqlConnection then everything works.
...
SqlConnection connection = new SqlConnection(sqlConnectionString);
ServerConnection srvCon = new ServerConnection(connection);
try
{
server = new Server(srvCon);
srvCon.BeginTransaction();
server.ConnectionContext.ExecuteNonQuery(script);
srvCon.CommitTransaction();
}
catch
{
srvCon.RollBackTransaction();
}
...

Related

Why is Transaction being Elevated to Distributed Transaction (MSDTC), Even after Closing 1st Connection and then Opening the 2nd Connection

I am trying this code which I think SHOULD NOT elevate/promote the TransactionScope to Distributed Transaction (MSDTC), because I read somewhere that MSDTC only happens under 2 conditions,
1. when we have a Nested TransactionScope
2. If we try to open 2 SIMULTANEOUS Connections to 2 different Sources within the same TransactionScope
But I am Closing the Earlier Connection and then Opening the New Connection to the Different Source, but still it is Promoting the Transaction to a Distributed one.
The Error I get is "The partner transaction manager has disabled its support for remote/network transactions."
Here is the Code:
var options = new TransactionOptions()
{
IsolationLevel = System.Transactions.IsolationLevel.RepeatableRead,
Timeout = TimeSpan.FromMinutes(5)
};
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, options))
{
// Connection To Server Database
string connectionString = "Server=188.188.188.188;Database=SomeDb;User=SomeUser;Password=SomePassword;Trusted_Connection=false;Connection Timeout=30;Persist Security Info=False";
SqlConnection conn1 = null;
try
{
conn1 = new SqlConnection(connectionString);
conn1.Open();
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
finally
{
if (conn1 != null)
{
conn1.Close();
conn1.Dispose();
conn1 = null;
}
}
// Connection To Local Machine Database
string connectionString2 = "Server=MyPC\\SqlServer2014;Database=SomeDb;User=SomeUser;Password=SomePassword;Trusted_Connection=false;Connection Timeout=30;Persist Security Info=False";
SqlConnection conn2 = null;
try
{
conn2 = new SqlConnection(connectionString2);
conn2.Open();
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
finally
{
conn2.Close();
conn2.Dispose();
conn2 = null;
}
scope.Complete();
}

Not able to connect to SQL Server database due to SSL encryption not being implemented

I'm trying to setup a connection between Unity and a SQL Server database, but I am currently unable to do so due to SSL encryption.
Here's the error:
Here's the code I'm using to try to make the connection
using System;
using System.Data;
using System.Data.SqlClient;
namespace DB.Services
{
public class DBServices
{
private const string _connectionString = #"Data Source=localhost\SQLEXPRESS;Initial Catalog=Players;Integrated Security=True;Trusted Connection=True";
private SqlConnection _db;
public string ConnectToDB()
{
_db = new SqlConnection(_connectionString);
_db.Open();
if (_db.State != ConnectionState.Open)
return "Connection failed";
var users = GetUsers();
return users;
}
private string GetUsers()
{
var query = "SELECT * FROM Player";
SqlDataAdapter cmd = new SqlDataAdapter(query, _db);
var result = cmd.SelectCommand.ExecuteNonQuery();
_db.Close();
return result.ToString();
}
}
}
Every other question I've seen has suggested that the connection string have 'Trusted Connection=True'. However, I continue to get the SSL encryption error.
Can anyone tell me what I'm doing wrong and what I need to do to fix it?

Using ODP.NET for Oracle 12.2c with IPC connections: NullReferenceException

After installing Oracle 12c Release 2, I am running into some problems with database and transaction handling. The version of the ODP.NET dll (Oracle.DataAccess.dll) is 4.122.1.0, and I am using a PC with Windows 7 Professional.
I am no longer able to use the OracleConnection.State property to monitor the state of a connection, which breaks existing code.
It seems that simply accessing the State property corrupts the OracleConnection object, but only when using IPC connections. Below is a code example that reproduces the problem. The database in this example is run on my local system.
private const string ConnectionStringIPC = #"Data Source=(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = IPC)(Key = EXTPROC1521))) (CONNECT_DATA = (SERVER = DEDICATED)(SERVICE_NAME = GLOBAL)));User Id=TestCase;Password=TestCase;Validate Connection=true;";
private const string ConnectionStringTCP = #"Data Source=(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))) (CONNECT_DATA = (SERVER = DEDICATED)(SERVICE_NAME = GLOBAL)));User Id=TestCase;Password=TestCase;Validate Connection=true;";
static void Main(string[] args)
{
Console.WriteLine("IPC:");
TestCase1(ConnectionStringIPC);
TestCase2(ConnectionStringIPC);
Console.WriteLine("TCP:");
TestCase1(ConnectionStringTCP);
TestCase2(ConnectionStringTCP);
}
private static void TestCase1(string connectionString)
{
try
{
OracleConnection conn = new OracleConnection(connectionString);
conn.Open();
OracleTransaction trans = conn.BeginTransaction();
Console.WriteLine("TestCase1 succesful!");
}
catch(Exception e)
{
Console.WriteLine("TestCase1 failed:");
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
}
private static void TestCase2(string connectionString)
{
try
{
OracleConnection conn = new OracleConnection(connectionString);
conn.Open();
var state = conn.State;
OracleTransaction trans = conn.BeginTransaction();
Console.WriteLine("TestCase2 succesful!");
}
catch (Exception e)
{
Console.WriteLine("TestCase2 failed:");
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
}
The output of this program is
IPC:
TestCase1 succesful!
TestCase2 failed:
Object reference not set to an instance of an object.
at Oracle.DataAccess.Client.OracleConnection.get_TxnHndAllocated()
at Oracle.DataAccess.Client.OracleConnection.BeginTransaction()
at OracleConnectionTest.Program.TestCase2(String connectionString)
TCP:
TestCase1 succesful!
TestCase2 succesful!
As you can see, simply accessing the OracleConnection.State property is enough to invalidate the object, triggering an exception in the subsequent OracleTransaction.BeginTransaction call.
Is there anything wrong with the way I try to use the OracleConnection and OracleTransaction objects?
If not, is this a known bug, and is there any good work-around?

Transaction Scope and Multiple Regions

Does transaction scope operate across multiple regions? If I have 2 Processes, one that opens a connection and transaction, performs a insert command then calls another process before the transaction is closed, Will the original transaction take into account if transaction 2 fails? Here is the example code below.
Region 1:
public static void process1()
{
using (SqlConnection conn = new SqlConnection(Connections.conn()))
{
//Open the connection
conn.Open();
try
{
//Create A new Sql transaction.
using (var trans = new System.Transactions.TransactionScope())
{
using (SqlCommand insert = new SqlCommand
{
CommandType = CommandType.Text,
CommandText = sql,
Connection = conn,
CommandTimeout = 300
})
{
insert.ExecuteNonQuery();
}
process2()
trans.complete();
}
}
catch (System.Data.SqlClient.SqlException ex)
{
string msg = "Insert Error:";
msg += ex.Message;
throw new Exception(msg);
}
}
}
Region 2
public static void process2()
{
using (SqlConnection conn = new SqlConnection(Connections.conn()))
{
//Open the connection
conn.Open();
try
{
//Create A new Sql transaction.
using (var trans2 = new System.Transactions.TransactionScope())
{
using (SqlCommand insert = new SqlCommand
{
CommandType = CommandType.Text,
CommandText = sql,
Connection = conn,
CommandTimeout = 300
})
{
insert.ExecuteNonQuery();
}
trans2.complete();
}
}
catch (System.Data.SqlClient.SqlException ex)
{
string msg = "Insert Error:";
msg += ex.Message;
throw new Exception(msg);
}
}
}
In my application process 2 is dependant on process 1's success. If process 1 is successful and process 2 is not then the result of process 1 is useless.
I understand that when the commans execute in the same transaction block they will both fail if one does but as I coded my application to do it accorss different regions I was wondering if the same applied in this situation. I would rather not having to recode two different processes together.
Thanks in advance,
Dan
If this is just two blocks of code within a single C# file, then to make sure either both processes happen or neither happen, you would want to wrap your call to those functions in a transaction scope as well. Like so:
using (var tx = new TransactionScope()) {
process1();
process2();
tx.Complete();
}
This way if either process1 or process2 fails, both will be rolled back.

cannot connect to oracle server from C#.net application

I'm trying to connect to remote Oracle server. My connection string -
OdbcConnection con = new OdbcConnection();
con.ConnectionString = #"Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST= xxxx)(PORT=xxxxx))(CONNECT_DATA=(SERVER=dedicated)(SERVICE_NAME=abc.domain.com)));USER ID=user1;Password=pwd;";
I encountered error saying - "ERROR [IM002] [Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified" (System.Data.Odbc.OdbcException) Exception Message = "ERROR [IM002] [Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified", Exception Type = "System.Data.Odbc.OdbcException", Exception WinRT Data = ""
I specified my connection string according to my TNSNAMES.ora
Entry for my DB in TNSNAMES.ora goes like this:
DB.WORLD=
(DESCRIPTION=
(ADDRESS=
(PROTOCOL=TCP)
(HOST= xxxx)
(PORT=xxxxx)
)
(CONNECT_DATA=
(SERVER=dedicated)
(SERVICE_NAME=abc.domain.com)
)
)
Can someone explain on the error. Please help/suggest if my connection string went wrong and how to connect to Oracle server from my windows application
first install odp.net.managed using nuget packet manager:
Install-Package odp.net.managed
odp.net.managed work without preinstalled Oracle Client
next:
const string connectionString = #"Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST= xxxx)(PORT=xxxxx))(CONNECT_DATA=(SERVER=dedicated)(SERVICE_NAME=abc.domain.com)));USER ID=user1;Password=pwd;";
var connection = new OracleConnection(connectionString);
connection.Open();
if you have tnsnames.ora in application folder:
const string connectionString = #"Data Source=DB.WORLD;USER ID=user1;Password=pwd;";
var connection = new OracleConnection(connectionString);
connection.Open();
or if tnsnames.ora in other folder:
Environment.SetEnvironmentVariable("TNS_ADMIN", #"path_to_tnsadmin.ora");
const string connectionString = #"Data Source=DB.WORLD;USER ID=user1;Password=pwd;";
var connection = new OracleConnection(connectionString);
connection.Open();
you need to use OracleConnection
OracleConnection conn = new OracleConnection(connectionString);
download and install Oracle Data Provider for .NET
Go to Connections Strings for Oracle
Maybe will find some help
Use following Code:
using System;
using Oracle.DataAccess.Client;
class ConnectionSample
{
static void Main()
{
OracleConnection con = new OracleConnection();
//using connection string attributes to connect to Oracle Database
con.ConnectionString = "User Id=scott;Password=tiger;Data Source=oracle";
con.Open();
Console.WriteLine("Connected to Oracle" + con.ServerVersion);
// Close and Dispose OracleConnection object
con.Close();
con.Dispose();
Console.WriteLine("Disconnected");
}
}
Source ONE , TWO and THREE
Try something like this class :
public class OracleOperations
{
OracleConnection oraConn = new OracleConnection();
private bool connStatus;
public OracleOperations()
{
connStatus = false;
connect();
}
~OracleOperations()
{
disconnect();
}
public bool getConnStatus()
{
return connStatus;
}
public void connect()
{
string connString = "User Id=xxxx; Password=yyyyy; Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=10.10.10.10)(PORT=1583))(CONNECT_DATA=(SERVER=dedicated)(SID=oracledb)))";
if (oraConn.State != ConnectionState.Open)
{
try
{
oraConn.ConnectionString = connString;
oraConn.Open();
Console.WriteLine("Successful Connection");
connStatus = true;
}
catch (Exception eOra)
{
Console.WriteLine(eOra.Message+ "Exception Caught");
connStatus = false;
throw eOra;
}
}
}
public void disconnect()
{
if (oraConn.State == ConnectionState.Open)
{
try
{
oraConn.Close();
connStatus = false;
Console.WriteLine("Connection Closed");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message + "Exception Caught");
}
}
}
}
I would try Tnsping utility to make sure you can connect via tnsnames.ora
Try putting tnsnames.ora and sqlnet.ora in the same folder of the application and see if that addresses the issue.
With Managed ODP.Net there is one catch it does not support LDAP look up (e.g. LDAP.ora)
I'Ve Created an app.config File and configured the DB entry like this
<configuration>
<configSections>
<section name ="Environment" type="System.Configuration.NameValueSectionHandler" />
</configSections>
<Environment>
<add key ="CIT" value ="Password=pwd123;User ID=abc123;Data Source=db1;Persist Security Info=True;Provider=MSDAORA"/>
<add key ="SIT" value ="Password=pwd234;User ID=abc234;Data Source=db2;Persist Security Info=True;Provider=MSDAORA"/>
<add key ="UAT" value ="Password=pwd345;User ID=abc345;Data Source=db3;Persist Security Info=True;Provider=MSDAORA"/>
</Environment>
</configuration>
Reffered that configuration into my form using ConfigurationManager(Need to refer the assembly - system.configuration). Add namespace - using System.Collections.Specialized to avail NameValueCollection. Code goes like this
environments = ConfigurationManager.GetSection("Environment") as NameValueCollection;
string strConnString = environments[envs];
conn = new OleDbConnection(strConnString);
conn.Open();
OleDbDataAdapter objDa = new OleDbDataAdapter("select * from tblABC", conn);
DataSet ds1 = new DataSet();
objDa.Fill(ds1); dataGridView1.DataSource = ds1.Tables[0];
Using datset, i've populated datagrid using an OleDbDataAdapter. It worked for my Windowsapplication.

Categories