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.
Related
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
I am useing kxml parser for my j2me application. I am reading the file from phone memory and parsing the xml file to display the data(have various level of filter). On each filter i need to read the data from this file. For first time i created the parser and every time i re-assign this parser1(reference-original) to the paerser2(used to parse data). For first time i got the correct answer, but second time i haven't got the file content it shows null as data.
Here is my code:
FileConnection fc = (FileConnection)Connector.open(rmsObj.rmsData.elementAt(0).toString());
InputStream in = fc.openInputStream();
InputStreamReader is = new InputStreamReader(in);
commonAppObj.externParser = new XmlParser(is);
commonAppObj class file.
protected void fileread() {
try {
if(externParser != null){
parser = externParser;
fileparser(parser);
}else{
InputStream in = this.getClass().getResourceAsStream(this.dataBase);
InputStreamReader is = new InputStreamReader(in);
parser = new XmlParser(is);
fileparser(parser);
}
} catch (IOException ioe) {
} finally {
parser = null;
}
}
private void fileparser(XmlParser parser){
try {
ParseEvent event = null;
dataflag = 0;
dataflagS = 0;
System.out.println("findtags = " + findtags);
while (((event = parser.read()).getType() != Xml.END_DOCUMENT) && (dataflag != 1)) {
if (event.getType() == Xml.START_TAG) {
String name = event.getName();
if (name != null && name.equals(findtags)) {
dataflag = 0;
parseAddressTag(parser);
}
name = null;
}
event = null;
}
} catch (IOException ioe) {
} finally {
parser = null;
}
}
}
If your InputStream returns true in a call to markSupported you may reset it at the end of fileparser method, but first you need to call mark right after creating it.
if (in.markSupported()) {
in.mark(in.available());
}
I tried to listen file change event in BlackBerry base on FileExplorer example, but whenever I added or deleted file, it always showed "Deferring persistence as device is being used" and I can't catch anything .Here is my code:
public class FileChangeListenner implements FileSystemJournalListener{
private long _lastUSN; // = 0;
public void fileJournalChanged() {
long nextUSN = FileSystemJournal.getNextUSN();
String msg = null;
for (long lookUSN = nextUSN - 1; lookUSN >= _lastUSN && msg == null; --lookUSN)
{
FileSystemJournalEntry entry = FileSystemJournal.getEntry(lookUSN);
// We didn't find an entry
if (entry == null)
{
break;
}
// Check if this entry was added or deleted
String path = entry.getPath();
if (path != null)
{
switch (entry.getEvent())
{
case FileSystemJournalEntry.FILE_ADDED:
msg = "File was added.";
break;
case FileSystemJournalEntry.FILE_DELETED:
msg = "File was deleted.";
break;
}
}
}
_lastUSN = nextUSN;
if ( msg != null )
{
System.out.println(msg);
}
}
}
Here is the caller:
Thread t = new Thread(new Runnable() {
public void run() {
new FileChangeListenner();
try {
Thread.sleep(5000);
createFile();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
t.start();
Create file method worked fine:
private void createFile() {
try {
FileConnection fc = (FileConnection) Connector
.open("file:///SDCard/newfile.txt");
// If no exception is thrown, then the URI is valid, but the file
// may or may not exist.
if (!fc.exists()) {
fc.create(); // create the file if it doesn't exist
}
OutputStream outStream = fc.openOutputStream();
outStream.write("test content".getBytes());
outStream.close();
fc.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
and output:
0:00:44.475: Deferring persistence as device is being used.
0:00:46.475: AG,+CPT
0:00:46.477: AG,-CPT
0:00:54.476: VM:+GC(f)w=11
0:00:54.551: VM:-GCt=9,b=1,r=0,g=f,w=11,m=0
0:00:54.553: VM:QUOT t=1
0:00:54.554: VM:+CR
0:00:54.596: VM:-CR t=5
0:00:55.476: AM: Exit net_rim_bb_datatags(291)
0:00:55.478: Process net_rim_bb_datatags(291) cleanup started
0:00:55.479: VM:EVTOv=7680,w=20
0:00:55.480: Process net_rim_bb_datatags(291) cleanup done
0:00:55.481: 06/25 03:40:41.165 BBM FutureTask Execute: net.rim.device.apps.internal.qm.bbm.platform.BBMPlatformManagerImpl$3#d1e1ec79
0:00:55.487: 06/25 03:40:41.171 BBM FutureTask Finish : net.rim.device.apps.internal.qm.bbm.platform.BBMPlatformManagerImpl$3#d1e1ec79
I also tried to remove the thread or create or delete file in simulator 's sdcard directly but it doesn't help. Please tell me where is my problem. Thanks
You instantiate the FileChangeListenner, but you never register it, and also don't keep it as a variable anywhere. You probably need to add this call
FileChangeListenner listener = new FileChangeListenner();
UiApplication.getUiApplication().addFileSystemJournalListener(listener);
You also might need to keep a reference (listener) around for as long as you want to receive events. But maybe not (the addFileSystemJournalListener() call might do that). But, you at least need that call to addFileSystemJournalListener(), or you'll never get fileJournalChanged() called back.
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();
}
I have a HTTP Connection on my application, for the current time being it is only applicable if the users are connected to WIFI connection. How would I do this if I'd like to enable it for any connections that the particular device has? Say that the device has a BIS service, or even a normal WAP service.
This is my code.
try
{
connection = (HttpConnection) Connector.open(url+ ";interface=wifi");
is = connection.openInputStream();
try
{
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
parser.parse(is, rssHandler);
}
catch (ParserConfigurationException e)
{
e.printStackTrace();
}
catch (SAXException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
catch (IOException e)
{
e.printStackTrace();
Dialog.inform("Bad URL");
}
Use the following code to get the connection string
/**
* Determines what connection type to use and returns the necessary string to use it.
* #return A string with the connection info
*/
private static String getConnectionString()
{
// This code is based on the connection code developed by Mike Nelson of AccelGolf.
// http://blog.accelgolf.com/2009/05/22/blackberry-cross-carrier-and-cross-network-http-connection
String connectionString = null;
// Simulator behavior is controlled by the USE_MDS_IN_SIMULATOR variable.
if(DeviceInfo.isSimulator())
{
if(UploaderThread.USE_MDS_IN_SIMULATOR)
{
logMessage("Device is a simulator and USE_MDS_IN_SIMULATOR is true");
connectionString = ";deviceside=false";
}
else
{
logMessage("Device is a simulator and USE_MDS_IN_SIMULATOR is false");
connectionString = ";deviceside=true";
}
}
// Wifi is the preferred transmission method
else if(WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED)
{
logMessage("Device is connected via Wifi.");
connectionString = ";interface=wifi";
}
// Is the carrier network the only way to connect?
else if((CoverageInfo.getCoverageStatus() & CoverageInfo.COVERAGE_DIRECT) == CoverageInfo.COVERAGE_DIRECT)
{
logMessage("Carrier coverage.");
String carrierUid = getCarrierBIBSUid();
if(carrierUid == null)
{
// Has carrier coverage, but not BIBS. So use the carrier's TCP network
logMessage("No Uid");
connectionString = ";deviceside=true";
}
else
{
// otherwise, use the Uid to construct a valid carrier BIBS request
logMessage("uid is: " + carrierUid);
connectionString = ";deviceside=false;connectionUID="+carrierUid + ";ConnectionType=mds-public";
}
}
// Check for an MDS connection instead (BlackBerry Enterprise Server)
else if((CoverageInfo.getCoverageStatus() & CoverageInfo.COVERAGE_MDS) == CoverageInfo.COVERAGE_MDS)
{
logMessage("MDS coverage found");
connectionString = ";deviceside=false";
}
// If there is no connection available abort to avoid bugging the user unnecssarily.
else if(CoverageInfo.getCoverageStatus() == CoverageInfo.COVERAGE_NONE)
{
logMessage("There is no available connection.");
}
// In theory, all bases are covered so this shouldn't be reachable.
else
{
logMessage("no other options found, assuming device.");
connectionString = ";deviceside=true";
}
return connectionString;
}
/**
* Looks through the phone's service book for a carrier provided BIBS network
* #return The uid used to connect to that network.
*/
private static String getCarrierBIBSUid()
{
ServiceRecord[] records = ServiceBook.getSB().getRecords();
int currentRecord;
for(currentRecord = 0; currentRecord < records.length; currentRecord++) { if(records[currentRecord].getCid().toLowerCase().equals("ippp")) { if(records[currentRecord].getName().toLowerCase().indexOf("bibs") >= 0)
{
return records[currentRecord].getUid();
}
}
}
return null;
}