How to make two insertion all successful and failure? - asp.net-mvc

In my recent project, for each user's payment, it needs to insert a Receipt and an Invoice into the SQL DB. I have 2 functions for it, InsertReceipt() and InsertInvoice(), so the code is like:
void DoPayment()
{
InsertReceipt();
InsertInvoice();
}
bool InsertReceipt()
{
// insert to SQL with a ReceiptId
// return true or false;
}
bool InsertInvoice()
{
// insert to SQL with an InvoiceId
// return true or false;
}
ReceiptId and InvoiceId have to be unique and consecutive here.
My question is, how can I do to make InsertReceipt() and InsertInvoice() all successful or all failure? Or I have to make a new function InsertReceiptAndInvoice(), and use SQL Transaction?

If you use a stored procedure, you absolutely can use transaction. You can read about transaction in Microsoft docs:
https://learn.microsoft.com/en-us/sql/t-sql/language-elements/begin-transaction-transact-sql?view=sql-server-ver15
With C#, you can use transaction with SqlConnection. Code example:
private static void ExecuteSqlTransaction(string connectionString)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlCommand command = connection.CreateCommand();
SqlTransaction transaction;
// Start a local transaction.
transaction = connection.BeginTransaction("SampleTransaction");
// Must assign both transaction object and connection
// to Command object for a pending local transaction
command.Connection = connection;
command.Transaction = transaction;
try
{
command.CommandText =
"Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')";
command.ExecuteNonQuery();
command.CommandText =
"Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')";
command.ExecuteNonQuery();
// Attempt to commit the transaction.
transaction.Commit();
Console.WriteLine("Both records are written to database.");
}
catch (Exception ex)
{
Console.WriteLine("Commit Exception Type: {0}", ex.GetType());
Console.WriteLine(" Message: {0}", ex.Message);
// Attempt to roll back the transaction.
try
{
transaction.Rollback();
}
catch (Exception ex2)
{
// This catch block will handle any errors that may have occurred
// on the server that would cause the rollback to fail, such as
// a closed connection.
Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType());
Console.WriteLine(" Message: {0}", ex2.Message);
}
}
}
}
You can read docs: https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlconnection.begintransaction?view=dotnet-plat-ext-3.1

Related

Slow performance while saving data in neo4j Enterprise Version (trail version)

Build 3 Node cluster in testing environment and used Neo4j-JDBC connection to save JSON data into Neo4j.
When creating just 2000 nodes and 2000 relations through JSON statistics are: Total time to save topology data in Neo4j: 456688 ms and links size: 2000, nodes size: 2000.
Saved without checking duplicacy of nodes/relations(Removed checkVertex and checkRelation methods):
Total time to save topology data in Neo4j: 446979 ms and links size: 2000, nodes size: 4000 (As we are not checking duplicacy, double nodes has been created).
Code:
public Connection getConnection(String masterNodeIp, String password) throws Exception {
return(Connection)DriverManager.getConnection("jdbc:neo4j:http://"+masterNodeIp+"/?user=neo4j,password="+password+"");
}
//By iterating through edges, Added source and target nodes.
try {
for (Links link : topology.getL2links()) {
if(conn != null) {
long srcId = etGraphIdByUniquenessOfOrphan(clientId,link.getSrcMgmtIP());
GraphId srcGraphId = prepareGraphId(srcId, "DEVICE");
long tgtId = etGraphIdByUniquenessOfOrphan(clientId,link.getTgtMgmtIP());
GraphId tgtGraphId = prepareGraphId(tgtId, "DEVICE");
String srcQuery = createNode(conn, link, false,clientId,discProfileId,
srcGraphId);
if(srcQuery!=null && !srcQuery.isEmpty())
stmt.execute(srcQuery);
String tgtQuery = createNode(conn, link, true,clientId,discProfileId,
tgtGraphId);
if(tgtQuery != null && !tgtQuery.isEmpty())
stmt.execute(tgtQuery);
String relationQuery = processRelation(conn, link,srcGraphId,tgtGraphId);
if(relationQuery!=null && !relationQuery.isEmpty())
stmt.execute(relationQuery);
}
}
} catch(Exception e) {
System.out.println("Exception in processJsonData ::: "+e.getMessage());
throw e;
} finally {
stmt.close();
conn.close();
}
//Before creating node checked whether node is already existed or not in order to avoid duplicacy
private boolean checkVertex(Connection conn, String ip, String hostName, long clientId, long discPId, GraphId graphId) throws Exception{
Statement stmt = null;
ResultSet rs = null;
boolean result=false;
try {
stmt = conn.createStatement();
StringBuffer queryBuffer = new StringBuffer();
queryBuffer.append(" MATCH (node) WHERE node.id ='"+graphId.getId()+"' AND node.sourceType = '"+graphId.getSourceType()+"'");
queryBuffer.append(" RETURN node");
rs = (ResultSet) stmt.executeQuery(queryBuffer.toString());
while(rs.next()) {
result=true;
break;
}
} catch(Exception e) {
System.out.println("Exception in fetching node ::: "+e.getMessage());
throw e;
} finally {
rs.close();
stmt.close();
}
return result;
}
//Before creating Relation also checked duplicacy for relationships.
private boolean checkRelation(Connection conn, Links link, GraphId srcGraphId, GraphId tgtGraphId) throws SQLException {
Statement stmt = null;
ResultSet rs = null;
boolean result=false;
try {
stmt = conn.createStatement();
StringBuffer queryBuffer = new StringBuffer();
queryBuffer.append(" MATCH (src:resource)-[r:topology]->(tgt:resource) WHERE src.id='"+srcGraphId.getId()
+"' AND tgt.id='"+tgtGraphId.getId()+"' AND r.srcInt='"+link.getSrcInt()+"'AND r.tgtInt='"+link.getTgtInt()+"'");
queryBuffer.append(" RETURN r");
rs=(ResultSet) stmt.executeQuery(queryBuffer.toString());
while(rs.next()) {
result=true;
break;
}
}
catch(Exception e) {
System.out.println("Exception in fetching node ::: "+e.getMessage());
} finally {
rs.close();
stmt.close();
}
return result;
}
We created indexes for those duplicacy check queries but still performance is slow.
And also please let us know how to use "Node key" unique constraint in Java level so that we can skip once checkVertex query. We tried to catch "constraintViolationexception" and added log instead of throwing it but it's throwing exception not saving any nodes.
There are a lot of things that you can improve:
for mass data imports use the Java Driver directly, JDBC adds an indirection layer
Use parameters!
Use batching, either with UNWIND or by executing multiple prepared statemts as batch
Don't construct queries with literal values.
Make sure you have indexes/constraints for your keys. Your queries don't use any indexes because you didn't provide any labels!
Use MERGE if you don't want to have constraint exceptions.
Don't use StringBuffer, ever.
Use try-with-resources
Use executeUpdate
For Batching:
https://medium.com/#mesirii/5-tips-tricks-for-fast-batched-updates-of-graph-structures-with-neo4j-and-cypher-73c7f693c8cc
For parameters:
http://neo4j-contrib.github.io/neo4j-jdbc/#_minimum_viable_snippet

SQL Try..Catch..Finally Errors Not Displaying

How can I get the SQLException error messages below to display?
I have a site where users upload a data file. I have intentionally added incorrect data (text to a field that only allows integers) as a test of my error handling. Nothing is rendering in the view. I am sure that an exception is being thrown, as none of the data is in the database. If I remove the incorrect field, everything uploads fine. I have also tried both ex.toString() and ex.message with no success.
In my view, I have:
#ViewBag.ErrorMessage
Controller:
using (SqlCommand command = new SqlCommand(sql2, con))
{
try
{
// long SQL statement
con.Open();
command.ExecuteNonQuery();
TempData["shortMessage"] = "Dataset Uploaded Successfully.";
}
catch (SqlException ex)
{
ViewBag.ErrorMessage = ex.ToString();
}
catch (Exception ex)
{
ViewBag.ErrorMessage = ex.ToString();
}
finally
{
con.Close();
}
}

org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool [duplicate]

This question already has answers here:
httpclient exception "org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection"
(10 answers)
Closed 8 years ago.
I use Multi-thread to scan the different URL in the same time in java. There was the bug,if the sum of request time exceed 100,000. I have already close which i should close. Here the code from my servlet
private String proyGetHttp(String url) throws ParseException, IOException,
InterruptedException {
String content = "";
getMethod = new HttpGet(url);
HttpResponse response = null;
HttpEntity httpEntity = null;
boolean success = false;
while (!success) {
System.out.println("url:" + url + ",connect...");
try {
response = client.execute(getMethod);
httpEntity = response.getEntity();
StringBuffer sb = new StringBuffer();
if (httpEntity != null) {
BufferedReader in = null;
InputStream instream = httpEntity.getContent();
try {
in = new BufferedReader(new InputStreamReader(instream));
String lineContent = "";
while(lineContent != null){
sb.append(lineContent);
lineContent = in.readLine();
}
} catch (Exception ex)
getMethod.abort();
throw ex;
} finally {
// Closing the input stream will trigger connection release
try { instream.close(); in.close();} catch (Exception ignore) {}
}
}
content = sb.toString();
success = true;
System.out.println("connect successfully...");
} catch (Exception e) {
e.printStackTrace();
getMethod.abort();
System.out.println("connect fail, please waitting...");
Thread.sleep(sleepTime);
}finally{
getMethod.releaseConnection();
}
}
return content;
}
Here code create the default client
PoolingClientConnectionManager cm = new PoolingClientConnectionManager();
cm.setMaxTotal(100);
DefaultHttpClient client = null;
client = new DefaultHttpClient(cm);
client.getParams().setParameter("http.protocol.cookie-policy", CookiePolicy.BROWSER_COMPATIBILITY);
client.getParams().setParameter(HttpConnectionParams.CONNECTION_TIMEOUT, 5000);
I have the same problem and I found the fix. This timeout is because of a connection leak. In my case, I'm using httpDelete method and not consuming the response. Instead, I'm checking the status of the response.
The fix is, the response entity need to be consumed. In order to ensure the proper release of system resources, one must close the content stream associated with the entity.
So I used EntityUtils.consumeQuietly(response.getEntity()); which ensures that the entity content is fully consumed and the content stream, if exists, is closed.

calling a webservice from scheduled task agent class in windows phone 7.1

Can we call a webservice from the scheduled periodic task class firstly, if yes,
Am trying to call a webservice method with parameters in scheduled periodic task agent class in windows phone 7.1. am getting a null reference exception while calling the method though am passing the expected values to the parameters for the webmethod.
am retrieving the id from the isolated storage.
the following is my code.
protected override void OnInvoke(ScheduledTask task)
{
if (task is PeriodicTask)
{
string Name = IName;
string Desc = IDesc;
updateinfo(Name, Desc);
}
}
public void updateinfo(string name, string desc)
{
AppSettings tmpSettings = Tr.AppSettings.Load();
id = tmpSettings.myString;
if (name == "" && desc == "")
{
name = "No Data";
desc = "No Data";
}
tservice.UpdateLogAsync(id, name,desc);
tservice.UpdateLogCompleted += new EventHandler<STservice.UpdateLogCompletedEventArgs>(t_UpdateLogCompleted);
}
Someone please help me resolve the above issue.
I've done this before without a problem. The one thing you need to make sure of is that you wait until your async read processes have completed before you call NotifyComplete();.
Here's an example from one of my apps. I had to remove much of the logic, but it should show you how the flow goes. This uses a slightly modified version of WebClient where I added a Timeout, but the principles are the same with the service that you're calling... Don't call NotifyComplete() until the end of t_UpdateLogCompleted
Here's the example code:
private void UpdateTiles(ShellTile appTile)
{
try
{
var wc = new WebClientWithTimeout(new Uri("URI Removed")) { Timeout = TimeSpan.FromSeconds(30) };
wc.DownloadAsyncCompleted += (src, e) =>
{
try
{
//process response
}
catch (Exception ex)
{
// Handle exception
}
finally
{
FinishUp();
}
};
wc.StartReadRequestAsync();
}
private void FinishUp()
{
#if DEBUG
try
{
ScheduledActionService.LaunchForTest(_taskName, TimeSpan.FromSeconds(30));
System.Diagnostics.Debug.WriteLine("relaunching in 30 seconds");
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
}
#endif
NotifyComplete();
}

SubSonic - Is it necessary to/how to explicitly close the database connection?

Traditionally when using a DbCommand when retrieving data from a sproc, something like the following is good practice:
DbCommand cmdDbCommand...
dbGetData = DatabaseFactory.CreateDatabase("MyDatabase");
cmdDbCommand = dbGetData.GetStoredProcCommand("MySproc");
.
.
.
try
{
...
}
catch (System.Exception ex)
{
if (cmdDbCommandcmdDbCommand != null)
{
if (cmdDbCommand.Connection.State == ConnectionState.Open)
{
cmdDbCommand.Connection.Close();
cmdDbCommand.Dispose();
}
}
}
Now, given the following type of SubSonic call:
try
{
StoredProcedure sp = SPs.GetSprocData(someID, result, errorMessage);
dsResults = sp.GetDataSet();
intResGetUserDetails = (int)sp.OutputValues[0];
errorMessage = (string)sp.OutputValues[1];
}
catch (System.Exception ex)
{
...
}
How can I explicitly ensure that the database connection has been closed?
The connection closes after the sproc is complete. This is built into Sobsonic 2.

Resources