Get changes from couchDB database using MyCouch - c#

I am trying to get the changes that have occurred in a couchDB database since the last time the code was executed. To do so, I have taken the following code from MYCouch library documentation. However, nothing is being printed and I am not sure why. I have made changes to the database between executions, but nothing is still printed and it is being exited with code 0. The problem is not with the database, since when I run a curl command for the changes from cmd, i get all the changes. So the error must be in the code
var cnInfo1 = new DbConnectionInfo("url", "mycompany")
{
Timeout = TimeSpan.FromMilliseconds(System.Threading.Timeout.Infinite)
};
using (var client = new MyCouchClient(cnInfo1))
{
var getChangesRequest = new GetChangesRequest
{
Feed = ChangesFeed.Continuous,
Since = "1",
Heartbeat = 3000
};
var cancellation = new CancellationTokenSource();
try
{
await client.Changes.GetAsync(
getChangesRequest,
data =>
{
Console.WriteLine("Within the data callback.");
if (data != null)
{
Console.WriteLine("Data is not null.");
foreach (var change in data)
{
Console.WriteLine(change);
}
}
else
{
Console.WriteLine("Data is null.");
}
},
cancellation.Token);
}
catch (Exception ex)
{
Console.WriteLine("Exception caught: " + ex.Message);
}

Related

Send row by row without duplicates

I have the following table
As you can see there is a column called Integration of type bool, all this table is shown in a DataGridView through a stored procedure that is this
CREATE PROCEDURE [dbo].[SP_Payments]
AS
SELECT 'CE-'+CardCode AS CardCode,DocType,Series,DocDate,dbo.udf_GetNumeric(DocNum) AS DocNum,
DocEntry,TrsfrAcct,TrsfrDate,TrsfrSum, Integration,Comments,SumApplied
FROM PaymentsReceived WHERE Integration = 0
This SP says to only show me those that are at 0 which is false, what I do with those that are false is to send them through a web service, I have a method that goes through each row and sends it every time it does a send sets it to true, then it disappears from the DataGridView, this method is inside a timer that fires every 5 seconds, in this method there is a condition that says if the Integration is == false, let it send, this is the method.
private async void Envio_Timer_Tick(object sender, EventArgs e)
{
try
{
ProxyBL proxy = new ProxyBL();
foreach (DataGridViewRow Datos in dataGridView1.Rows)
{
PagosRecibidos pagos = new PagosRecibidos
{
CardCode = Convert.ToString(Datos.Cells[0].Value),
DocType = Convert.ToString(Datos.Cells[1].Value),
Series = Convert.ToInt32(Datos.Cells[2].Value),
DocDate = Convert.ToDateTime(Datos.Cells[3].Value),
DocEntry = Convert.ToInt32(Datos.Cells[5].Value),
TrsfrAcct = Convert.ToString(Datos.Cells[6].Value),
TrsfrDate = Convert.ToDateTime(Datos.Cells[7].Value),
TrsfrSum = Convert.ToDecimal(Datos.Cells[8].Value),
Integration = Convert.ToBoolean(Datos.Cells[9].Value),
Comments = Convert.ToString(Datos.Cells[10].Value),
SumApplied = Convert.ToDecimal(Datos.Cells[11].Value)
};
Inte = pagos.Integration;
if (Inte == false)
{
var EnvioDatos = await proxy.EnviarPago(pagos);
}
ListarEmple();
ListarLog();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
This is the method where SendPayment comes in
This method I get the response from Services, where if the operation was successful or failed, it inserts this in a Log
Consultas c = new Consultas();
public async Task<string> EnviarPago(PagosRecibidos detalle)
{
try
{
ProxyXML xmlProxy = new ProxyXML();
string respuesta = await xmlProxy.EnviarSAP(detalle);
c.InsertarLog(1, DateTime.Now, respuesta, xmlProxy.XmlSerializado);
return respuesta;
}
catch (Exception ex)
{
throw ex;
}
}
After this method, enter the shipment, EnviaSAP
Which is where I capture the answer, if the operation was successful then give me the Integration column as "1 true"
readonly Consultas c = new Consultas();
public string XmlSerializado = null;
public async Task<string> EnviarSAP(PagosRecibidos detalle)
{
try
{
using (WSSincronizacionClient clienteSAP = new WSSincronizacionClient())
{
XmlSerializado = this.SerializarXml(detalle);
var respuesta = await clienteSAP.EnviarDatosSAPAsync(XmlSerializado);
if (respuesta.Contains("true|OperaciĆ³n Exitosa|"))
{
c.EditarIntegration(true, Convert.ToInt32(detalle.DocEntry));
}
return respuesta;
}
}
catch (Exception ex)
{
throw ex;
}
}
Everything works correctly but when sending it, sometimes it sends it double or duplicate, that is, in SAP it arrives twice, how can I do this validation, that the one that is false only enters me once, that it does not send it for any reason twice , and in which part should I do this validation
I also don't know why if you already have that validation that I only sent the fake ones, you still send it twice.
The only thing I can think of is that the time to process an individual row exceeds the timer interval, therefore you might be iterating over the same item in two handler calls in parallel, because there isn't enough time for the other handler to complete its processing.
Maybe you could flag the row when you're fetching it, and save the changes so that flag could act as a discriminator for other timer tick handler calls to ignore the row:
foreach (DataGridViewRow Datos in dataGridView1.Rows)
{
var alreadyProcessingRow = Convert.ToBoolean(Datos.Cells[{ProcessingFlagColumnIndex}].Value);
if(alreadyProcessingRow)
continue; //skip the row, don't reprocess it
Datos.Cells[{ProcessingFlagColumnIndex}] = true; //Mark the row as processing
PagosRecibidos pagos = new PagosRecibidos
{
CardCode = Convert.ToString(Datos.Cells[0].Value),
DocType = Convert.ToString(Datos.Cells[1].Value),
Series = Convert.ToInt32(Datos.Cells[2].Value),
DocDate = Convert.ToDateTime(Datos.Cells[3].Value),
DocEntry = Convert.ToInt32(Datos.Cells[5].Value),
TrsfrAcct = Convert.ToString(Datos.Cells[6].Value),
TrsfrDate = Convert.ToDateTime(Datos.Cells[7].Value),
TrsfrSum = Convert.ToDecimal(Datos.Cells[8].Value),
Integration = Convert.ToBoolean(Datos.Cells[9].Value),
Comments = Convert.ToString(Datos.Cells[10].Value),
SumApplied = Convert.ToDecimal(Datos.Cells[11].Value)
};
Inte = pagos.Integration;
if (Inte == false)
{
var EnvioDatos = await proxy.EnviarPago(pagos);
}
Datos.Cells[{ProcessingFlagColumnIndex}] = false; //reset the flag (not that important if you just don't care after processing)
ListarEmple();
ListarLog();
}
I'm not really sure if you can do that with that datagridview object, but in case you couldn't you could use something like a ConcurrentDictionary, and store the rows (or row Ids) you are currently processing there in order to check and avoid duplicate processing.

BLE Read operation not working in view model for Xamarin forms

I'm trying to do BLE implementation in Xamarin forms. So I am able to connect and do write operation successfully but when I do read operation the app crashes. The read operation works in code behind that is xaml.cs but it crashes in viewmodel. This is exception I'm getting
Assertion at
/Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/mono/mini/debugger-agent.c:4660,
condition is_ok (error)' not met, function:get_this_async_id, Could not execute the method because the containing type 'System.Runtime.CompilerServices.AsyncTaskMethodBuilder1[TReturn_REF]',
is not fully instantiated. assembly: type: member:(null) [libc] Fatal signal 6 (SIGABRT), code -1
(SI_QUEUE) in tid 24845 (twell.touchless), pid 24845 (twell.touchless)
This is my code in viewmodel
private async Task<string> ProcessDeviceInformationService(IService deviceInfoService)
{
try
{
await adapter.ConnectToDeviceAsync(device);
var sb = new StringBuilder("Getting information from Device Information service: \n");
var characteristics = await deviceInfoService.GetCharacteristicsAsync();
var characteristic = await deviceInfoService.GetCharacteristicAsync(Guid.Parse("00002A39-0000-1000-8000-00805F9B34FB"));
// characteristic.CanWrite = true;
//foreach (var characteristic in characteristics)
//{
try
{
if (Device.RuntimePlatform==Device.iOS)
{
characteresticnativedata = DependencyService.Get<ICharacteristiciOS>();
characteresticnativedata.OpeniosBluetooth(device);
}
if (characteristic != null)
{
var sbnew = new StringBuilder("BLE Characteristics\n");
byte[] senddata = Encoding.UTF8.GetBytes(string.IsNullOrEmpty(SendMessageLabel.Text) ? "0ab" : SendMessageLabel.Text);
if (MainThread.IsMainThread)
{
var newbytes = await characteristic.WriteAsync(senddata);
}
var charvalue = Characteristic.Value;
var bytes = await characteristic.ReadAsync();
string str = Encoding.UTF8.GetString(charvalue);
sbnew.AppendLine($"Characteristics found on this device: {string.Join(", ", str.ToString())}");
CharactericsLabel.Text = sbnew.ToString();
}
}
catch (Exception ex)
{
return ex.Message;
}
return CharactericsLabel.Text;
}
catch (Exception ex)
{
return ex.ToString();
}
}
This same code var bytes = await characteristic.ReadAsync(); works in xaml.cs but it crashes in viewmodel. I even used GetAwaiter().GetResult() instead of await. But still it crashes.
var bytes = characteristic.ReadAsync.GetAwaiter().GetResult();
I have no clue how to fix this any suggestions?

How to close SQLite Connection in Xamarin Forms?

I have a code the gets data from my server. Every data will be inserted in my local database (SQLite Database) one by one. Every once in a whole I am getting these two errors. My codes below is where the exception are always appearing.
SQLite.SQLiteException: Busy
SQLite.SQLiteException: database is locked
What is/are the cause(s) why I always get these exceptions?
Update:
I added await conn.CloseAsync(); in every end of the code is that correct?
here is my first code, it will inquire to the server if there were updates and if there are updates it will insert or replace(update) the data in my local database:
var db = DependencyService.Get<ISQLiteDB>();
var conn = db.GetConnection();
string apifile = "sync-retailer-outlet-server-update-api.php";
var lastchecked = Preferences.Get("retaileroutletchangelastcheck", String.Empty, "private_prefs");
int count = 0;
var uri = new Uri(string.Format("http://" + domain + "/TBSApp/app_api/" + apifile + "?Host=" + host + "&Database=" + database + "&ContactID=" + contact + "&LastChecked=" + lastchecked, string.Empty));
try
{
SyncStatus("Getting retailer outlet data from server");
var response = await client.GetAsync(uri);
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(content))
{
var dataresult = JsonConvert.DeserializeObject<List<RetailerGroupData>>(content, settings);
var datacount = dataresult.Count;
for (int i = 0; i < datacount; i++)
{
SyncStatus("Saving retailer outlet server update to local database (" + (count + 1) + " out of " + dataresult.Count + ")");
var item = dataresult[i];
var retailerCode = item.RetailerCode;
var insertdata = new RetailerGroupTable
{
RetailerCode = retailerCode
};
await conn.InsertOrReplaceAsync(insertdata);
count++;
}
}
}
}
catch (Exception ex)
{
Crashes.TrackError(ex);
}
await conn.CloseAsync();
Here is the other code that creates the local database table everytime the StartPage is loaded.
public async void CreateTableAsync()
{
try
{
var db = DependencyService.Get<ISQLiteDB>();
var conn = db.GetConnection();
if (conn != null)
{
try
{
await conn.CreateTableAsync<UserTable>();
await conn.CreateTableAsync<ContactsTable>();
await conn.CreateTableAsync<ActivityTable>();
await conn.CreateTableAsync<CAFTable>();
await conn.CreateTableAsync<RetailerGroupTable>();
await conn.CreateTableAsync<UserEmailTable>();
await conn.CreateTableAsync<UserLogsTable>();
await conn.CreateTableAsync<SubscriptionTable>();
await conn.CreateTableAsync<ProvinceTable>();
await conn.CreateTableAsync<TownTable>();
}
catch (Exception ex)
{
Console.Write("Creating table error " + ex.Message);
}
}
}
catch (Exception ex)
{
Crashes.TrackError(ex);
await DisplayAlert("Application Error", "Error:\n\n" + ex.Message.ToString() + "\n\n Please contact your administrator", "Ok");
}
}
await conn.CloseAsync();
using (SQLiteConnection connection = db.GetConnection())
{
// Do whatever you want to do with your active connection
}
Note that you cannot reuse that connection outside the scope of the using block and have to get a new connection the same way the next time you want to access your database.
According to your description and code, I assume you use async-style inserts and are on different threads and thus an insert is timing out waiting for the lock of a different insert to complete. You can use synchronous inserts to avoid this condition.

Programmatically Import Block Into AutoCAD (C#)

I'm writing a plugin for AutoCAD and want to import all the blocks it will use at the beginning to make sure that they are available when needed. To do that, I use this method
public static void ImportBlocks(string[] filesToTryToImport, string filter = "")
{
foreach (string blockToImport in filesToTryToImport)
{
if (blockToImport.Contains(filter))
{
Database sourceDb = new Database(false, true); //Temporary database to hold data for block we want to import
try
{
sourceDb.ReadDwgFile(blockToImport, System.IO.FileShare.Read, true, ""); //Read the DWG into a side database
ObjectIdCollection blockIds = new ObjectIdCollection(); // Create a variable to store the list of block identifiers
Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = sourceDb.TransactionManager;
using (Transaction myT = tm.StartTransaction())
{
// Open the block table
BlockTable bt = (BlockTable)tm.GetObject(sourceDb.BlockTableId, OpenMode.ForRead, false);
// Check each block in the block table
foreach (ObjectId btrId in bt)
{
BlockTableRecord btr = (BlockTableRecord)tm.GetObject(btrId, OpenMode.ForRead, false);
// Only add named & non-layout blocks to the copy list
if (!btr.IsAnonymous && !btr.IsLayout)
{
blockIds.Add(btrId);
}
btr.Dispose();
}
}
// Copy blocks from source to destination database
IdMapping mapping = new IdMapping();
sourceDb.WblockCloneObjects(blockIds, _database.BlockTableId, mapping, DuplicateRecordCloning.Replace, false);
_editor.WriteMessage("\nCopied " + blockIds.Count.ToString() + " block definitions from " + blockToImport + " to the current drawing.");
}
catch (Autodesk.AutoCAD.Runtime.Exception ex)
{
_editor.WriteMessage("\nError during copy: " + ex.Message);
}
finally
{
sourceDb.Dispose();
}
}
}
}
That method appears to work because it successfully executes. However when I go to insert a block in the drawing via AutoCAD's interface it doesn't show up as an option and when I try to insert it programmatically it throws a FileNotFound exception meaning it didn't work. What's wrong with this method? Thanks in advance!
EDIT: Here is a less complicated method with a test method
public static void ImportSingleBlock(string fileToTryToImport)
{
using (Transaction tr = _database.TransactionManager.StartTransaction())
{
Database sourceDb = new Database(false, true); //Temporary database to hold data for block we want to import
try
{
sourceDb.ReadDwgFile(fileToTryToImport, System.IO.FileShare.Read, true, ""); //Read the DWG into a side database
_database.Insert(fileToTryToImport, sourceDb, false);
_editor.WriteMessage("\nSUCCESS: " + fileToTryToImport);
}
catch (Autodesk.AutoCAD.Runtime.Exception ex)
{
_editor.WriteMessage("\nERROR: " + fileToTryToImport);
}
finally
{
sourceDb.Dispose();
}
tr.Commit();
}
}
[CommandMethod("TESTSINGLEBLOCKIMPORTING")]
public void TestSingleBlockImporting()
{
OpenFileDialog ofd = new OpenFileDialog();
DialogResult result = ofd.ShowDialog();
if (result == DialogResult.Cancel) //Ending method on cancel
{
return;
}
string fileToTryToImport = ofd.FileName;
using (Transaction tr = _database.TransactionManager.StartTransaction())
{
EntityMethods.ImportSingleBlock(fileToTryToImport);
tr.Commit();
}
}
This file is the block I'm trying to import. Hope this inspires someone cause I am desperately lost right now.
Your code is correct and should work. In fact I did tried it and works fine. You're probably missing to Commit() a outer transaction (where you call this ImportBlocs() method). Check:
using (Transaction trans = _database.TransactionManager.StartTransaction())
{
ImportBlocks(... parameters here ...);
trans.Commit(); // remember to call this commit, if omitted, Abort() is assumed
}
I had the same issue, very similar code. Issue was that
_database.Insert(fileToTryToImport, sourceDb, false);
should be
_database.Insert(blockName, sourceDb, false);
You can see that the first parameter has to be "blockName", and not the file path.

How do I trap Cancelling of a long-running deferred DTF Custom Action?

I've got a Deferred Custom Action DLL written in DTF that publishes a set of .RDL files to the SQL Server Reporting Web Service. All is working well and I can trap most of the error conditions in various Try Catch blocks.
The only thing I am having trouble with is if the user presses the Cancel button in the installer while the publish is happening. It does immediately pop up a message asking if I want to Cancel the install, but if I answer Yes then it throws a message :
Exception of type Microsoft.Deployment.WindowsInstaller.InstallCanceledException was thrown
and just an OK button.
I've tried adding a special Exception handler of
catch (InstallCanceledException ex)
{
}
prior to other exceptions, but it just doesn't seem to capture this one particular exception.
Any suggestions how to handle the InstallCanceledException during a Cancel of a long-running Deferred Custom Action?
The product team looked at using one of the applications but normal users run the applications and they wouldn't necessarily know the web service URL or have permissions to publish the reports to the web service. The installer I have put this in is usually used for running SQL Scripts and I'm adding a second Feature to the installer to Publish the reports. It's actually working too well to abandon it now. Product has seen what I've done already and they love it. The MSI Progress Bar is updating with the name of each report as they are published. The MSI prompts for the URI and user credentials and it already knows what folder the .RDL files are in. I run a Validation on the URI when they click the next button so by the time I run the Deferred action in the Execution Sequence it has a good URI and credentials. I've even gone so far as while the publish is occurring I disconnect from VPN and it fails with a proper error. It is literally only when the user presses Cancel that I can't seem to trap that one, but it is also not a showstopper for this work to go out.
Hiding the Cancel button is not an appropriate option since it is fine if they Cancel at any time.
public static ActionResult PublishSSRSReports(Session session)
{
session.Log("Begin PublishSSRSReports");
bool bFolderExists = false;
string sCustomActionData;
sCustomActionData = session["CustomActionData"];
string INSTALLDIR = Convert.ToString(MsiGetCustomActionDataAttribute(sCustomActionData, "/InstallDir="));
string SSRSURL = Convert.ToString(MsiGetCustomActionDataAttribute(sCustomActionData, "/SsrsUrl="));
string USERCREDENTIALS = Convert.ToString(MsiGetCustomActionDataAttribute(sCustomActionData, "/Credentials="));
string USERNAME = Convert.ToString(MsiGetCustomActionDataAttribute(sCustomActionData, "/Username="));
string PASSWORD = Convert.ToString(MsiGetCustomActionDataAttribute(sCustomActionData, "/Password="));
string ReportsFolderPath = INSTALLDIR + "SSRSReports";
DirectoryInfo directory = new DirectoryInfo(ReportsFolderPath);
FileInfo[] reports = directory.GetFiles("*.rdl"); //Getting all RDL files
ResetProgressBar(session, reports.Length);
CatalogItem[] catalogitem = null;
using (ReportingService2010 rsc = new ReportingService2010())
{
rsc.Url = SSRSURL;
if (USERCREDENTIALS == "0")
{
rsc.Credentials = System.Net.CredentialCache.DefaultCredentials; //User credential for Reporting Service
//the current logged system user
}
if (USERCREDENTIALS == "1")
{
string[] userdomain = USERNAME.Split(Convert.ToChar("\\"));
rsc.Credentials = new System.Net.NetworkCredential(userdomain[1], PASSWORD, userdomain[0]);
}
catalogitem = rsc.ListChildren(#"/", false);
foreach (CatalogItem catalog in catalogitem)
{
if (catalog.Name == (DP))
{
EventLog.WriteEntry(AppDomain.CurrentDomain.FriendlyName, DP + " folder already exists");
bFolderExists = true;
}
}
if (bFolderExists == false)
{
rsc.CreateFolder(DP, #"/", null);
}
Warning[] Warnings = null;
foreach (FileInfo ReportFile in reports)
{
Byte[] definition = null;
Warning[] warnings = null;
try
{
FileStream stream = ReportFile.OpenRead();
definition = new Byte[stream.Length];
stream.Read(definition, 0, (int)stream.Length);
stream.Close();
}
catch (InstallCanceledException ex)
{
//session.Message(InstallMessage.Error, new Record { FormatString = ex.Message });
EventLog.WriteEntry(AppDomain.CurrentDomain.FriendlyName, ex.Message);
return ActionResult.UserExit;
}
catch (IOException ex)
{
session.Message(InstallMessage.Error, new Record { FormatString = ex.Message });
EventLog.WriteEntry(AppDomain.CurrentDomain.FriendlyName, ex.Message);
return ActionResult.Failure;
}
catch (Exception ex)
{
session.Message(InstallMessage.Error, new Record { FormatString = ex.Message });
EventLog.WriteEntry(AppDomain.CurrentDomain.FriendlyName, ex.Message);
return ActionResult.Failure;
}
try
{
CatalogItem report = rsc.CreateCatalogItem("Report", ReportFile.Name, #"/" + DP, true, definition, null, out Warnings);
DisplayActionData(session, ReportFile.Name);
IncrementProgressBar(session, 1);
if (report != null)
{
EventLog.WriteEntry(AppDomain.CurrentDomain.FriendlyName, ReportFile.Name + " Published Successfully ");
}
if (warnings != null)
{
foreach (Warning warning in warnings)
{
EventLog.WriteEntry(AppDomain.CurrentDomain.FriendlyName, string.Format("Report: {0} has warnings", warning.Message));
}
}
else
{
EventLog.WriteEntry(AppDomain.CurrentDomain.FriendlyName, string.Format("Report: {0} created successfully with no warnings", ReportFile.Name));
}
}
catch (InstallCanceledException ex)
{
//session.Message(InstallMessage.Error, new Record { FormatString = ex.Message });
EventLog.WriteEntry(AppDomain.CurrentDomain.FriendlyName, ex.Message);
return ActionResult.UserExit;
}
catch (SoapException ex)
{
session.Message(InstallMessage.Error, new Record { FormatString = ex.Message });
EventLog.WriteEntry(AppDomain.CurrentDomain.FriendlyName, ex.Detail.InnerXml.ToString());
return ActionResult.Failure;
}
catch (Exception ex)
{
session.Message(InstallMessage.Error, new Record { FormatString = ex.Message });
EventLog.WriteEntry(AppDomain.CurrentDomain.FriendlyName, ex.Message);
return ActionResult.Failure;
}
}
}
return ActionResult.Success;
I've also got these in the class
private const string SpaceForwardSlash = " /";
private const string DP = "Test";
In the DTF source code the only place I see an InstallCanceledException being thrown is in Session.Message(). This is a wrapper for the MsiProcessMessage Windows API function. It looks to me like you would get this exception if you used Session.Message() to display a message box from a managed custom action, and then clicked the 'Cancel' button. DTF sees the message box 'cancel' return code and throws an InstallCanceledException. Perhaps it's then falling into a catch block somewhere (could be a different action?) where you call something similar to
session.Message(InstallMessage.Error, new Record { FormatString = ex.Message })
which displays the second message box containing just the exception.
I can't quite piece everything together 100% without seeing your MSI source or a complete log file, but maybe this will help.
Here's how Session.Message() is defined in the DTF source:
public MessageResult Message(InstallMessage messageType, Record record)
{
if (record == null)
{
throw new ArgumentNullException("record");
}
int ret = RemotableNativeMethods.MsiProcessMessage((int) this.Handle, (uint) messageType, (int) record.Handle);
if (ret < 0)
{
throw new InstallerException();
}
else if (ret == (int) MessageResult.Cancel)
{
throw new InstallCanceledException();
}
return (MessageResult) ret;
}

Categories