Problem with SQLite in iOS App with Xamarin forms - c#

I have created my app in Visual Studio 2019 for Android and iOS.
If I DEBUG my iOS app it is working perfectly as it should. It is debugged with iPhoneSimulator.
But if I rollout my RELEASE and test in on for example iPad, it seems that it can not find the SQLite DB whitch is stored like this:
string dbpath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "MyDatabase.db");
Is there a problem maybe with the SpecialFolder 'Personal' on iOS?
This code will be processes during start up:
if (!File.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "MyDatabase.db")))
{
DataHelper.Database db = new DataHelper.Database();
if (!db.CreateDatabase())
{
DisplayAlert("Error", "DB could not be loaded !", "OK");
}
}
this is my DatabaseHelper class:
namespace VoTa.DataHelper
{
public class Database
{
readonly string dbpath = Data.GetPath();
private static readonly string ftpurl = "myURL";
public bool CreateDatabase()
{
try
{
var connection = new SQLiteConnection(dbpath);
connection.CreateTable<Belohnungen>();
connection.CreateTable<Vokabeln>();
connection.CreateTable<EigeneVokabel>();
connection.Close();
return true;
}
catch (SQLiteException)
{
//Log.Info("SQLite Fehler!", ex.Message);
return false;
}
}
public void InsertIntoVokabeln(string dateiname)
{
String voakbelURL = ftpurl + dateiname;
string id;
string fremdsprache;
string deutsch;
string info1;
string info2;
var connection = new SQLiteConnection(dbpath);
connection.Query<Vokabeln>("Delete from Vokabeln");
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(voakbelURL);
var vList = xmldoc.SelectNodes("/Vokabel/VokabelModel");
try
{
foreach (XmlNode node in vList)
{
id = node["Id"].InnerText;
fremdsprache = node["fremdsprache"].InnerText;
deutsch = node["deutsch"].InnerText;
info1 = "";
info2 = "";
if (node["info1"] != null)
{
info1 = node["info1"].InnerText;
}
if (node["info2"] != null)
{
info1 = node["info2"].InnerText;
}
Vokabeln vokabel = new Vokabeln
{
Fremdsprache = fremdsprache,
Deutsch = deutsch,
Info1 = info1,
Info2 = info2
};
connection.Insert(vokabel);
}
}
catch (Exception)
{
return;
}
finally
{
connection.Close();
}
}
public void InsertIntoBelohnungen(string dateiname)
{
String belohunngURL = ftpurl + dateiname;
string id;
string beloh;
string info1;
string info2;
var connection = new SQLiteConnection(dbpath);
connection.Query<Belohnungen>("Delete from Belohnungen");
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(belohunngURL);
var vList = xmldoc.SelectNodes("/Belohnung/BelohnungModel");
try
{
foreach (XmlNode node in vList)
{
id = node["Id"].InnerText;
beloh = node["Belohnung"].InnerText;
info1 = "";
info2 = "";
if (node["info1"] != null)
{
info1 = node["info1"].InnerText;
}
if (node["info2"] != null)
{
info1 = node["info2"].InnerText;
}
Belohnungen belohnung = new Belohnungen
{
Belohnung = beloh,
Info1 = info1,
Info2 = info2
};
connection.Insert(belohnung);
}
}
catch (Exception)
{
return;
}
finally
{
connection.Close();
}
}
It is working on iPhoneSimulator but not in "real".
Add DB file in the AppDelegate.cs file like:
string sqliteFilename = "MyDatabase.db";
string folderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal),"..","Library");
string dbpath = Path.Combine(folderPath, sqliteFilename);
LoadApplication(new App(dbpath));
My App.xaml.cs:
public App(string dbpath)
{
InitializeComponent();
Data.SetPath(dbpath);
MainPage = new NavigationPage(new MainPage());
}
My MainView:
switch (Device.RuntimePlatform)
{
case Device.iOS:
if (!File.Exists(Data.GetPath()))
{
DataHelper.Database db = new DataHelper.Database();
if (!db.CreateDatabase())
{
DisplayAlert("Fehler", "Datenbank konnte nicht erstellt werden !", "OK");
}
}
break;
case Device.Android:
if (!File.Exists(Data.GetPath()))
{
DataHelper.Database db = new DataHelper.Database();
if (!db.CreateDatabase())
{
DisplayAlert("Fehler", "Datenbank konnte nicht erstellt werden !", "OK");
}
}
break;
}
This does not gave me exception.
I get this exception:
private void Starten()
{
DataHelper.Database db = new DataHelper.Database();
try
{
List<Vokabeln> myvokabel = db.SelectTableVokabeln(anzahlVokabel).ToList();
frage.Clear();
antwort.Clear();
info1.Clear();
info2.Clear();
belohnung.Clear();
int test = myvokabel.Count();
foreach (var item in myvokabel)
{
if (richtung == 1)
{
frage.Add(item.Deutsch);
antwort.Add(item.Fremdsprache);
}
else
{
frage.Add(item.Fremdsprache);
antwort.Add(item.Deutsch);
info1.Add(item.Info1);
info2.Add(item.Info2);
}
}
List<Belohnungen> mybelohnung = db.SelectTableBelohnungen().ToList();
foreach (var bel in mybelohnung)
{
belohnung.Add(bel.Belohnung);
}
//DisplayAlert("Info", "Vokabeln und Belohnungen wurden geladen!", "OK");
}
catch (Exception)
{
//Log.Info("interner Fehler!", ex.Message);
DisplayAlert("Fehler", "Es ist ein Fehler aufgetreten", "OK");
}
}
Database.cs
public List<Vokabeln> SelectTableVokabeln(int anzahl)
{
try
{
var connection = new SQLiteConnection(dbpath);
var abfrage = connection.Query<Vokabeln>(string.Format("SELECT ID, Fremdsprache, Deutsch, Info1, Info2 FROM Vokabeln ORDER BY RANDOM() LIMIT {0}", anzahl));
//return connection.Table<Vokabeln>().ToList();
return abfrage;
}
catch (SQLiteException)
{
//Log.Info("SQLite Fehler!", ex.Message);
return null;
}
}
public List<Belohnungen> SelectTableBelohnungen()
{
try
{
var connection = new SQLiteConnection(dbpath);
return connection.Table<Belohnungen>().ToList();
}
catch (SQLiteException)
{
//Log.Info("SQLite Fehler!", ex.Message);
return null;
}
}
Any help?
Thank you.

I remember having had similar issues when trying to handle the file in shared code.
Strangely enough, creating an interface in my shared code with a native implementation on both iOS and Android resolved the issue.
Here is my code to retrieve the connection from within my iOS project in a native implementation of an interface from the shared project called IFileService:
public SQLite.SQLiteConnection GetDbConnection()
{
try
{
string sqliteFilename = "MyAppDb.db3";
string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal) + sqliteFilename);
SQLiteConnection conn = new SQLite.SQLiteConnection(path, SQLiteOpenFlags.Create | SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.NoMutex);
return conn;
}
catch (Exception ex)
{
Logger.Fatal(ex, "An exception occurred at GetConnection");
Logger.Trace("Stack Trace: {0}", ex.StackTrace);
}
return null;
}
Also I would suggest that you don't access your connection the way you are doing it right now, as
var connection = new SQLiteConnection(dbpath);
will keep your connection open, which will most probably cause problems, if you want to use another connection.
In order to ensure that your connection is properly closed, I would highly recommend to manage it in a using block:
using(SQLiteConnection connection = iFileService.GetDbConnection())
{
connection.CreateTable<Belohnungen>();
connection.CreateTable<Vokabeln>();
connection.CreateTable<EigeneVokabel>();
}
This way the connection will be properly closed and disposed when your database access is finished. Also ensure that you always access your database connections that way whenever you get or store data in SQLite.
P.S.: if you are using a newer version of sqlite, you might need to construct your database with
SQLiteConnection connection = new SQLiteConnection(dbpath);
instead of the way I am creating it.

Related

My Web Service throws an System.AggregateException when I upload files larger than 2MB to SharePoint Online

My web service was working fine. When a file is larger than 2MB, it throws System.AggregateException in System.Private.CoreLib.dll.
can you give me some suggestion?
Below is the exception:
Exception thrown: 'System.AggregateException' in System.Private.CoreLib.dll
An unhandled exception of type 'System.AggregateException' occurred in System.Private.CoreLib.dll
One or more errors occurred.
System.AggregateException
HResult=0x80131500
Message=One or more errors occurred. (The server was unable to process the request due to an internal error. For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework SDK documentation and inspect the server trace logs.)
Source=System.Private.CoreLib
StackTrace:
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.Wait()
at sharepoint.Program.Main(String[] args) in C:\Users\Qihong.Kuang\source\repos\WebService\sharepoint\Program.cs:line 11
Inner Exception 1:
FaultException: The server was unable to process the request due to an internal error. For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework SDK documentation and inspect the server trace logs.
static void Main(string[] args)
{
Console.WriteLine("Uploading...");
ServiceReference1.ServiceClient ws = new ServiceReference1.ServiceClient();
//something happened in this Async task;
ws.start_processAsync().Wait();
Console.WriteLine("Upload Finished!");
}
public class Service : IService
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite == null)
{
throw new ArgumentNullException("composite");
}
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
public void start_process()
{
WebService ws = new WebService();
ws.GetCredentials();
}
}
public class WebService : System.Web.Services.WebService
{
OracleConnection con;
List<int> file_ids = new List<int>();
int file_id2;
string queryString;
OracleCommand cmd;
OracleDataReader dtr;
byte[] g_file = new byte[0];
string file_name;
ClientContext ctx;
public WebService()
{
//Uncomment the following line if using designed components
//InitializeComponent();
}
public void StartProcess()
{
var startTimeSpan = TimeSpan.Zero;
var periodTimeSpan = TimeSpan.FromSeconds(30);
var timer = new System.Threading.Timer((e) =>
{
GetCredentials();
}, null, startTimeSpan, periodTimeSpan);
}
public void GetCredentials()
{
var siteUrl = "siteURL";
var user = "USER";
var password = "PASSWORD";
var pwd = new SecureString();
string docLib = "testtest";
foreach (var c in password) pwd.AppendChar(c);
var SPOCredentials = new SharePointOnlineCredentials(user, pwd);
var SPCredentials = new NetworkCredential(user, pwd);
string subfolderPath = GetSubFolder();
file_ids = GetFileID();
//string uploadLocation = GetFileName();
foreach (var file_id in file_ids)
{
file_id2 = file_id;
ExecuteType("file_name");
string uploadLocation = file_name;
using (ctx = new ClientContext(siteUrl))
{
try
{
ctx.Credentials = SPOCredentials;
ctx.ExecuteQuery();
}
catch (ClientRequestException)
{
ctx.Credentials = SPCredentials;
ctx.ExecuteQuery();
}
catch (NotSupportedException)
{
ctx.Credentials = SPCredentials;
ctx.ExecuteQuery();
Console.WriteLine("SharePoint On-Premise");
}
var library = ctx.Web.Lists.GetByTitle(docLib);
var fileBytes = new byte[] { };
//fileBytes = ReadData();
ExecuteType("blob");
FileStream fileStream;
fileBytes = g_file;
//fileStream = new FileStream(g_file, FileMode.Open);
var fileCreationInformation = new FileCreationInformation();
uploadLocation = string.Format("{0}/{1}", subfolderPath, uploadLocation);
uploadLocation = string.Format("{0}/{1}/{2}", siteUrl, docLib, uploadLocation);
fileCreationInformation.Content = fileBytes;
fileCreationInformation.Overwrite = true;
fileCreationInformation.Url = uploadLocation;
//Upload the file to root folder of the Document library
library.RootFolder.Files.Add(fileCreationInformation);
ctx.ExecuteQuery();
DeleteRecordAfterUploadToSharePoint();
}
}
}
public void ExecuteType(string executeType)
{
con = new OracleConnection(GetConnectionString());
queryString = GetQueryString();
try
{
con.Open();
OracleCommand cmd = new OracleCommand(queryString, con);
dtr = cmd.ExecuteReader();
while (dtr.Read())
{
if (executeType == "file_name")
{
file_name = Convert.ToString(dtr["file_name"]);
}
else if (executeType == "blob")
{
g_file = (byte[])dtr["actual_file"];
}
}
}
catch (Exception ex)
{
string showError = "Error: " + ex.Message;
}
finally
{
dtr.Close();
con.Close();
}
}
public void DeleteRecordAfterUploadToSharePoint()
{
con = new OracleConnection(GetConnectionString());
string queryString = GetDeleteQueryString();
try
{
con.Open();
cmd = new OracleCommand(queryString, con);
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
string showError = "Error: " + ex.Message;
}
finally
{
con.Close();
}
}
public List<int> GetFileID()
{
con = new OracleConnection(GetConnectionString());
string queryString = "select count(file_id), file_id from nfirs.sharepoint_file group by file_id";
OracleDataReader dtr = null;
try
{
con.Open();
OracleCommand cmd = new OracleCommand(queryString, con);
dtr = cmd.ExecuteReader();
while (dtr.Read())
{
file_ids.Add(Convert.ToInt32(dtr["file_id"]));
}
}
catch (Exception ex)
{
string showError = "Error: " + ex.Message;
}
finally
{
dtr.Close();
con.Close();
}
Console.WriteLine(file_ids);
return file_ids;
}
public int GetIndividualFileID()
{
return file_id2;
}
public string GetSubFolder()
{
DateTime dt = Convert.ToDateTime(DateTime.Now);
string year = dt.Year.ToString();
return year;
}
public string GetConnectionString()
{
return "Data Source=(DESCRIPTION =(connectionStringhere)";
}
public string GetQueryString()
{
return "select file_id, file_type, actual_file, file_name, file_mimetype, file_update_dttm, file_charset from nfirs.Sharepoint_File where file_id = " + GetIndividualFileID();
}
public string GetDeleteQueryString()
{
string deleteQuery = "delete from (" + GetQueryString() + ")";
return deleteQuery;
}
public string GetFileName()
{
con = new OracleConnection(GetConnectionString());
queryString = GetQueryString();
//OracleDataReader dtr = null;
//string file_name = "";
try
{
con.Open();
OracleCommand cmd = new OracleCommand(queryString, con);
dtr = cmd.ExecuteReader();
while (dtr.Read())
{
file_name = Convert.ToString(dtr["file_name"]);
}
}
catch (Exception ex)
{
string showError = "Error: " + ex.Message;
}
finally
{
dtr.Close();
con.Close();
}
return file_name;
}
public byte[] ReadData()
{
//OracleConnection con = new OracleConnection(GetConnectionString());
//List<int> file_ids = GetFileID();
//foreach(var file_id in file_ids)
//{
//}
string queryString = GetQueryString();
//OracleDataReader dtr = null;
//byte[] g_file = new byte[0];
try
{
con.Open();
cmd = new OracleCommand(queryString, con);
dtr = cmd.ExecuteReader();
while (dtr.Read())
{
g_file = (byte[])dtr["actual_file"];
}
}
catch (Exception ex)
{
string showError = "Error: " + ex.Message;
}
finally
{
dtr.Close();
con.Close();
}
return g_file;
}
}
Instead of using byte[], use memorystream

System.OutOfMemoryException in C# when Generating huge amount of byte[] objects

I'm using this code to modify a pdf tmeplate to add specific details to it,
private static byte[] GeneratePdfFromPdfFile(byte[] file, string landingPage, string code)
{
try
{
using (var ms = new MemoryStream())
{
using (var reader = new PdfReader(file))
{
using (var stamper = new PdfStamper(reader, ms))
{
string _embeddedURL = "http://" + landingPage + "/Default.aspx?code=" + code + "&m=" + eventCode18;
PdfAction act = new PdfAction(_embeddedURL);
stamper.Writer.SetOpenAction(act);
stamper.Close();
reader.Close();
return ms.ToArray();
}
}
}
}
catch(Exception ex)
{
File.WriteAllText(HttpRuntime.AppDomainAppPath + #"AttachmentException.txt", ex.Message + ex.StackTrace);
return null;
}
}
this Method is being called from this Method:
public static byte[] GenerateAttachment(AttachmentExtenstion type, string Contents, string FileName, string code, string landingPage, bool zipped, byte[] File = null)
{
byte[] finalVal = null;
try
{
switch (type)
{
case AttachmentExtenstion.PDF:
finalVal = GeneratePdfFromPdfFile(File, landingPage, code);
break;
case AttachmentExtenstion.WordX:
case AttachmentExtenstion.Word:
finalVal = GenerateWordFromDocFile(File, code, landingPage);
break;
case AttachmentExtenstion.HTML:
finalVal = GenerateHtmlFile(Contents, code, landingPage);
break;
}
return zipped ? _getZippedFile(finalVal, FileName) : finalVal;
}
catch(Exception ex)
{
return null;
}
}
and here is the main caller,
foreach (var item in Recipients)
{
//...
//....
item.EmailAttachment = AttachmentGeneratorEngine.GenerateAttachment(_type, "", item.AttachmentName, item.CMPRCode, _cmpTmp.LandingDomain, _cmpTmp.AttachmentZip.Value, _cmpTmp.getFirstAttachment(item.Language, item.DefaultLanguage));
}
The AttachmentGeneratorEngine.GenerateAttachment method is being called approx. 4k times, because I'm adding a specific PDF file from a PDF template for every element in my List.
recently I started having this exception:
Exception of type 'System.OutOfMemoryException' was thrown. at System.IO.MemoryStream.ToArray()
I already implemented IDisposible in the classes and and I made sure that all of them are being released.
Note: it was running before very smoothely and also I double checked the system's resources - 9 GB is used out of 16 GB, so I had enough memory available.
==========================================
Update:
Here is the code that loops through the list
public static bool ProcessGroupLaunch(string groupCode, int customerId, string UilangCode)
{
CampaignGroup cmpGList = GetCampaignGroup(groupCode, customerId, UilangCode)[0];
_campaigns = GetCampaigns(groupCode, customerId);
List<CampaignRecipientLib> Recipients = GetGroupRcipientsToLaunch(cmpGList.ID, customerId);
try
{
foreach (var item in _campaigns)
item.Details = GetCampaignDetails(item.CampaignId.Value, UilangCode);
Stopwatch stopWatch = new Stopwatch();
#region single-threaded ForEach
foreach (var item in Recipients)
{
CampaignLib _cmpTmp = _campaigns.FirstOrDefault(x => x.CampaignId.Value == item.CampaignId);
bool IncludeAttachment = _cmpTmp.IncludeAttachment ?? false;
bool IncludeAttachmentDoubleBarrel = _cmpTmp.IncludeAttachmentDoubleBarrel ?? false;
if (IncludeAttachment)
{
if (_cmpTmp.AttachmentExtension.ToLower().Equals("doc") || (_cmpTmp.AttachmentExtension.ToLower().Equals("docx")))
_type = AttachmentGeneratorEngine.AttachmentExtenstion.Word;
else if (_cmpTmp.AttachmentExtension.ToLower().Equals("ppt") || (_cmpTmp.AttachmentExtension.ToLower().Equals("pptx")))
_type = AttachmentGeneratorEngine.AttachmentExtenstion.PowePoint;
else if (_cmpTmp.AttachmentExtension.ToLower().Equals("xls") || (_cmpTmp.AttachmentExtension.ToLower().Equals("xlsx")))
_type = AttachmentGeneratorEngine.AttachmentExtenstion.Excel;
else if (_cmpTmp.AttachmentExtension.ToLower().Equals("pdf"))
_type = AttachmentGeneratorEngine.AttachmentExtenstion.PDF;
else if (_cmpTmp.AttachmentExtension.ToLower().Equals("html"))
_type = AttachmentGeneratorEngine.AttachmentExtenstion.HTML;
}
//set "recpient" details
item.EmailFrom = _cmpTmp.EmailFromPrefix + "#" + _cmpTmp.EmailFromDomain;
item.EmailBody = GetChangedPlaceHolders((_cmpTmp.getBodybyLangCode(string.IsNullOrEmpty(item.Language) ? item.DefaultLanguage : item.Language, item.DefaultLanguage)), item.ID, _cmpTmp.CustomerId.Value, _cmpTmp.CampaignId.Value);
if (item.EmailBody.Contains("[T-LandingPageLink]"))
{
//..
}
if (item.EmailBody.Contains("[T-FeedbackLink]"))
{
//..
}
if (item.EmailBody.Contains("src=\".."))
{
//..
}
//set flags to be used by the SMTP Queue and Scheduler
item.ReadyTobeSent = true;
item.PickupReady = false;
//add attachment to the recipient, if any.
if (IncludeAttachment)
{
item.AttachmentName = _cmpTmp.getAttachmentSubjectbyLangCode(string.IsNullOrEmpty(item.Language) ? item.DefaultLanguage : item.Language, item.DefaultLanguage) + "." + _cmpTmp.AttachmentExtension.ToLower();
try
{
if (_type == AttachmentGeneratorEngine.AttachmentExtenstion.PDF || _type == AttachmentGeneratorEngine.AttachmentExtenstion.WordX || _type == AttachmentGeneratorEngine.AttachmentExtenstion.Word)
item.EmailAttachment = AttachmentGeneratorEngine.GenerateAttachment(_type, "", item.AttachmentName, item.CMPRCode, _cmpTmp.LandingDomain, _cmpTmp.AttachmentZip.Value, _cmpTmp.getFirstAttachment(item.Language, item.DefaultLanguage));
else item.EmailAttachment = AttachmentGeneratorEngine.GenerateAttachment(_type, value, item.AttachmentName, item.CMPRCode, _cmpTmp.LandingDomain, _cmpTmp.AttachmentZip.Value);
item.AttachmentName = _cmpTmp.AttachmentZip.Value ? (_cmpTmp.getAttachmentSubjectbyLangCode(string.IsNullOrEmpty(item.Language) ? item.DefaultLanguage : item.Language, item.DefaultLanguage) + ".zip") :
_cmpTmp.getAttachmentSubjectbyLangCode(string.IsNullOrEmpty(item.Language) ? item.DefaultLanguage : item.Language, item.DefaultLanguage) + "." + _cmpTmp.AttachmentExtension.ToLower();
}
catch (Exception ex)
{
}
}
else
{
item.EmailAttachment = null;
item.AttachmentName = null;
}
}
#endregion
stopWatch.Stop();
bool res = WriteCampaignRecipientsLaunch(ref Recipients);
return res;
}
catch (Exception ex)
{
Recipients.ForEach(i => i.Dispose());
cmpGList.Dispose();
Recipients = null;
cmpGList = null;
return false;
}
finally
{
Recipients.ForEach(i => i.Dispose());
cmpGList.Dispose();
Recipients = null;
cmpGList = null;
}
}

C# async method does not return to caller as expected

I have a series of asynchronous functions that are cascaded, but when it finishes executing the last, it does not return the values ​​to the previous ones.
This is where my first call is run. This is a WebAPI function and always comes to an end.
[HttpGet]
[Route("integracao/iniciar")]
public IHttpActionResult FazerIntegrar()
{
try
{
Integrar objIntegrar = new Integrar();
return Ok(objIntegrar.Integra());
}
catch (Exception ex)
{
return InternalServerError(ex);
}
}
so my function is in my library is called. Within my function I have a for executing only once. The flow is never resumed by it to continue the loop
public async Task<bool> Integra()
{
var files = Directory.GetFiles(#"C:\inetpub\wwwroot\Atendup\Arquivos\Backup\");
bool retorno = false;
if (files != null)
{
foreach (var item in files)
{
retorno = false;
using (StreamReader sr = new StreamReader(item))
{
if (sr != null)
{
while (sr.EndOfStream == false)
{
string line = await sr.ReadLineAsync();
string[] grupo = line.Split(new[] { "#*#" }, StringSplitOptions.None);
procData objProc = new procData();
objProc.proc = grupo[0];
objProc.name = JsonConvert.DeserializeObject<List<string>>(grupo[1]);
objProc.valor = JsonConvert.DeserializeObject<List<object>>(grupo[2]);
objProc.tipo = JsonConvert.DeserializeObject<List<Type>>(grupo[3]);
_context = new IntegrarRepository("online_pedidopizza");
retorno = await _context.IntegrarAsync(objProc);
//retorno = await _context.IntegrarAsync(objProc);
}
}
}
if (retorno == true)
{
await DeleteAsync(item);
}
}
}
return retorno;
}
I have a third function just to mediate with the repository
public async Task<bool> IntegrarAsync(procData objProc)
{
return await this.SendIntegrarAsync(objProc);
}
And finally, communication with the database, all code is executed correctly. Debugging you can get to the end of this fourth function but then the debug stop and does not go back to the beginning
protected async Task<bool> SendIntegrarAsync(procData parametro)
{
bool retorno = false;
using (SqlConnection conn = new SqlConnection(""))
{
using (SqlCommand cmd = new SqlCommand(parametro.proc, conn))
{
cmd.CommandType = CommandType.StoredProcedure;
if (parametro != null)
{
for (int i = 0; i < parametro.name.Count; i++)
{
AdicionaParametro(cmd, parametro.name[i], parametro.valor[i], parametro.tipo[i]);
}
}
try
{
cmd.CommandTimeout = 300;
await conn.OpenAsync().ConfigureAwait(false);
var resultado = await cmd.ExecuteScalarAsync().ConfigureAwait(false);
if (resultado != null)
{
retorno = Convert.ToBoolean(resultado);
}
}
catch (Exception ex)
{
Logs objLog = new Logs()
{
metodo = MethodBase.GetCurrentMethod().Name,
classe = this.GetType().Name,
dados = parametro,
data = DateTime.Now,
mensagem = ex.Message,
exception = ex.InnerException == null ? "" : ex.InnerException.ToString()
};
objLog.Adiciona();
string name = DateTime.Now.ToBinary().ToString();
using (StreamWriter sw = new StreamWriter(#"C:\inetpub\wwwroot\Atendup\Arquivos\Backup\" + name + ".txt"))
{
string line = "";
line += parametro.proc + "#*#";
line += JsonConvert.SerializeObject(parametro.name) + "#*#";
line += JsonConvert.SerializeObject(parametro.valor) + "#*#";
line += JsonConvert.SerializeObject(parametro.tipo) + "#*#";
sw.WriteLine(line);
}
}
}
}
return retorno;
}
What should I have to do? Thanks
Your Web Api call is not async try changing it to:
[HttpGet]
[Route("integracao/iniciar")]
public async Task<IHttpActionResult> FazerIntegrar()
{
try
{
Integrar objIntegrar = new Integrar();
return Ok(await objIntegrar.Integra());
}
catch (Exception ex)
{
return InternalServerError(ex);
}
}

C# - "Connection must be valid and open" with multiple Queries and Methods | Connection not closed?

For many hours now I have lost it over this same error no matter what I change.
I'm trying to make a command line application that will retrieve info from a database based off of two argument inputs, the modname and the optional author. The queries are all handled in the jobs.cs file. The entry-point file calls the method beginJob() which gets the target modname and author (if specified) to query. What's different from the hundred or so other posts I've read here is that the first query issued works completely fine, and I'm sure to close the reader and connection. (Won't close connection every time in production, but I did here for debugging purposes). The next time I call the connection it results in this error.
System.InvalidOperationException: Connection must be valid and open.
at MySql.Data.MySqlClient.ExceptionInterceptor.Throw(Exception exception)
at MySql.Data.MySqlClient.MySqlConnection.Throw(Exception ex)
at MySql.Data.MySqlClient.MySqlCommand.CheckState()
at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior)
at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader()
at vmcmod.Job.queryAuthor(String authorUID) in F:\Projects\VisualStudio\VMC-MOD\vmcmod\job.cs:line 235
at vmcmod.Job.StartJob() in F:\Projects\VisualStudio\VMC-MOD\vmcmod\job.cs:line 47
at vmcmod.Job.queryModAndAuthor(String modname, String author) in F:\Projects\VisualStudio\VMC-MOD\vmcmod\job.cs:line 205
at vmcmod.Job.beginJob() in F:\Projects\VisualStudio\VMC-MOD\vmcmod\job.cs:line 27
at vmcmod.VMCMOD.parseArgs() in F:\Projects\VisualStudio\VMC-MOD\vmcmod\vmcmod.cs:line 58
Some posts I've looked at but don't seem to help:
C# Mysql Connection must be valid and open
Connection must be valid and open error
C# Query: 'System.InvalidOperationException' | Additional information: Connection must be valid and open
C# Source Files (Please try and not cringe too hard, this is my first C# application):
jobs.cs [updated]
using MySql.Data.MySqlClient;
using System;
namespace vmcmod
{
class Job
{
public bool checkInput()
{
if (Global.currentJobTargetModname == "undefined")
{
Utils.consoleLog("The mod name is required.", 3);
return false;
}
else
{
return true;
}
}
public void beginJob()
{
string targetModname = Global.currentJobTargetModname.ToLower();
string targetModAuthor = Global.currentJobTargetAuthor.ToLower();
if (targetModAuthor != "undefined")
{
queryModAndAuthor(targetModname, targetModAuthor);
Utils.consoleLog("Job Call. (Author defined)", 4);
}
else
{
queryMod(targetModname);
Utils.consoleLog("Job Call. (Author undefined)", 4);
}
}
private void StartJob()
{
string author = null;
string targetModAuthor = Global.currentJobTargetAuthor.ToLower();
Utils.consoleLog("Mod exists.", 5);
if (targetModAuthor == "undefined")
{
author = "(None; First in row)";
}
else
{
queryAuthor(Global.queryResModAuthorID);
author = "'" + Global.queryResModAuthor + "' (UUID:" + Global.queryResModAuthorID + ") ";
}
var collaborators_obj = Newtonsoft.Json.Linq.JObject.Parse(Global.queryResModCollab);
var tags_obj = Newtonsoft.Json.Linq.JObject.Parse(Global.queryResModTags);
Console.BackgroundColor = ConsoleColor.Blue;
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("MOD INSTALL SPECIFICATIONS:");
Console.BackgroundColor = ConsoleColor.Black;
Console.WriteLine(" Mod Name: '" + Global.queryResModName + "'");
Console.Write(" Mod Author: " + author);
if (Global.queryResModAuthorVerified == true && targetModAuthor != "undefined")
{
Utils.consoleTag("*VERIFIED*", ConsoleColor.Green);
}
if (Global.queryResModAuthorVerified == false && targetModAuthor != "undefined")
{
Utils.consoleTag("*UNVERIFIED*", ConsoleColor.Red);
}
Console.Write("\n");
Console.WriteLine(" Mod Version: " + Global.queryResModVersion);
Console.WriteLine(" Installations: " + Global.queryResModInstalls);
Console.WriteLine(" Description:\n " + Global.queryResDescription);
Console.WriteLine(" Mod UUID: " + Global.queryResModUid);
if (Global.advInfo == true)
{
Console.WriteLine(" Rep. Entry #" + Global.queryResModID);
Console.WriteLine(" Mod Created On: " + Utils.UnixTimeStampToDateTime(Convert.ToDouble(Global.queryResDateCreated)));
Console.WriteLine(" Mod Last Modified On: " + Utils.UnixTimeStampToDateTime(Convert.ToDouble(Global.queryResDateLastModf)));
Console.WriteLine(" Tags: \n " + Convert.ToString(tags_obj["tags"]));
Console.WriteLine(" Collaborators: \n " + Convert.ToString(collaborators_obj["collaborators"]));
}
Utils.consoleSeparator();
bool user_response = Utils.consoleAskYN("Are you sure you want to install this mod?");
if (user_response == true)
{
queryGetModJSON(Global.queryResModUid);
Utils.consoleLog("JSON Data: "+Global.queryResModJSON,5);
//FileIO fio = new FileIO();
//fio.jsonToFiles(fio.jsonToArray(Global.queryResModJSON));
}
else
{
Utils.consoleSetKeyExit();
}
}
private void queryGetModJSON(string uuid)
{
var dbCon = new DBConnection();
if (dbCon.IsConnect() == false)
{
Utils.consoleLog("Unable to query repository or no results.", 3);
Utils.consoleSetKeyExit();
}
else
{
string q = "SELECT data_json FROM vmcmod_repository_data WHERE uid='" + uuid + "' LIMIT 1;";
MySqlCommand cmd = new MySqlCommand(q, dbCon.Connection);
var reader = cmd.ExecuteReader();
if (!reader.HasRows)
{
Utils.consoleLog("Mod data not found.", 3);
reader.Close();
dbCon.Close();
}
else
{
while (reader.Read())
{
Global.queryResModJSON = reader.GetString(0);
}
reader.Close();
dbCon.Close();
}
}
}
private void queryMod(string modname)
{
var dbCon = new DBConnection();
if (dbCon.IsConnect() == false)
{
Utils.consoleLog("Unable to query repository or no results.", 3);
Utils.consoleSetKeyExit();
}
else
{
string q = "SELECT id,uid,author_id,mod_name,status,dependencies_json,description,mod_version,date_created,date_last_modified,collaborators,tags_json,installs FROM vmcmod_repository_info WHERE mod_name LIKE'" + modname + "' LIMIT 1;";
MySqlCommand cmd = new MySqlCommand(q, dbCon.Connection);
var reader = cmd.ExecuteReader();
if (!reader.HasRows)
{
Utils.consoleLog("Mod not found.", 3);
reader.Close();
dbCon.Close();
}
else
{
while (reader.Read())
{
Global.queryResModInstalls = reader.GetInt32(12);
Global.queryResModTags = reader.GetString(11);
Global.queryResModCollab = reader.GetString(10);
Global.queryResDateLastModf = reader.GetInt32(9);
Global.queryResDateCreated = reader.GetInt32(8);
Global.queryResModVersion = reader.GetFloat(7);
Global.queryResDescription = reader.GetString(6);
Global.queryResModDependencies = reader.GetString(5);
Global.queryResModStatus = reader.GetInt16(4);
Global.queryResModName = reader.GetString(3);
Global.queryResModAuthorID = reader.GetString(2);
Global.queryResModUid = reader.GetString(1);
Global.queryResModID = Convert.ToInt32(reader.GetInt32(0));
}
reader.Close();
dbCon.Close();
StartJob();
}
}
}
private void queryModAndAuthor(string modname, string author)
{
var dbCon = new DBConnection();
if (dbCon.IsConnect() == false)
{
Utils.consoleLog("Unable to query repository or no results.", 3);
Utils.consoleSetKeyExit();
}
else
{
string q = "SELECT id,uid,author_id,mod_name,status,dependencies_json,description,mod_version,date_created,date_last_modified,collaborators,tags_json,installs FROM vmcmod_repository_info WHERE mod_name LIKE'" + modname + "' LIMIT 1;";
MySqlCommand cmd = new MySqlCommand(q, dbCon.Connection);
var reader = cmd.ExecuteReader();
if (!reader.HasRows)
{
Utils.consoleLog("Mod not found.", 3);
reader.Close();
dbCon.Close();
}
else
{
while (reader.Read())
{
Global.queryResModInstalls = reader.GetInt32(12);
Global.queryResModTags = reader.GetString(11);
Global.queryResModCollab = reader.GetString(10);
Global.queryResDateLastModf = reader.GetInt32(9);
Global.queryResDateCreated = reader.GetInt32(8);
Global.queryResModVersion = reader.GetFloat(7);
Global.queryResDescription = reader.GetString(6);
Global.queryResModDependencies = reader.GetString(5);
Global.queryResModStatus = reader.GetInt16(4);
Global.queryResModName = reader.GetString(3);
Global.queryResModAuthorID = reader.GetString(2);
Global.queryResModUid = reader.GetString(1);
Global.queryResModID = Convert.ToInt32(reader.GetInt32(0));
}
reader.Close();
dbCon.Close();
StartJob();
}
}
}
private bool queryCheckAuthorExists(string author)
{
var dbCon = new DBConnection();
string q = "SELECT * FROM vmcmod_users WHERE username='"+author+ "' AND is_author=true LIMIT 1;";
MySqlCommand cmd = new MySqlCommand(q, dbCon.Connection);
var reader = cmd.ExecuteReader();
if (reader.HasRows == false)
{
Utils.consoleLog("Author not found.", 3);
reader.Close();
dbCon.Close();
return false;
}
else
{
Utils.consoleLog("Author found.", 4);
reader.Close();
dbCon.Close();
return true;
}
}
private void queryAuthor(string authorUID)
{
var dbCon = new DBConnection();
string q = "SELECT username,is_verified_user FROM vmcmod_users WHERE uid='" + authorUID + "' AND is_author=true LIMIT 1;";
MySqlCommand cmd = new MySqlCommand(q, dbCon.Connection);
var reader = cmd.ExecuteReader();
if (reader.HasRows == false)
{
Utils.consoleLog("Author not found.", 3);
reader.Close();
dbCon.Close();
}
else
{
while (reader.Read())
{
Global.queryResModAuthor = reader.GetString(0);
Global.queryResModAuthorVerified = reader.GetBoolean(1);
}
Utils.consoleLog("Author found.", 4);
reader.Close();
dbCon.Close();
}
}
}
}
dbinterface.cs (this wasn't written by me, rather taken and edited from a post on stackoverflow, here) [updated]
using MySql.Data.MySqlClient;
using System;
namespace vmcmod
{
public class DBConnection
{
public DBConnection()
{
}
public string Password { get; set; }
private MySqlConnection connection = null;
public MySqlConnection Connection
{
get { return connection; }
}
public bool IsConnect()
{
bool result = true;
if (Connection == null)
{
string connString = "Server=...; Port=...; Database=...; Uid=...; Pwd=...;";
connection = new MySqlConnection(connString);
try
{
connection.Open();
Utils.consoleLog("Connected to repository.", 4);
result = true;
}
catch (Exception e)
{
Utils.consoleLog("Error occured while connecting to repository.", 3);
Utils.consoleLog("MySQL Exception: "+e,5);
result = false;
}
}
return result;
}
public void Close()
{
connection.Close();
connection = null;
}
}
}
global.cs (global variable storage)
using System;
namespace vmcmod
{
class Global
{
internal const float version = 0.1F;
internal static string currentJobWorld = "New World";
internal static string currentJobTargetModname = "undefined";
internal static string currentJobTargetAuthor = "undefined";
internal static string currentJobProfile = "default";
internal static int currentJobAccountPIN;
internal static bool verbose = false;
internal static bool debug = false;
internal static bool advInfo = false;
internal static bool queryResModAuthorVerified = false;
internal static string queryResModUid;
internal static string queryResModAuthorID;
internal static string queryResModAuthor;
internal static string queryResModName;
internal static string queryResModDependencies = "{\"dependencies\":[]}";
internal static int queryResModStatus;
internal static float queryResModVersion;
internal static string queryResDescription = "None provided.";
internal static int queryResDateCreated;
internal static int queryResDateLastModf;
internal static int queryResModID;
internal static string queryResModCollab = "{\"collaborators\":[]}";
internal static string queryResModTags = "{\"tags\":[]}";
internal static int queryResModInstalls;
internal static string queryResModJSON = "{}";
}
}
The quick and dirty solution would be to change:
public void Close()
{
connection.Close();
}
to:
public void Close()
{
connection.Close();
connection = null;
}
Also, remove this code:
private static DBConnection _instance = null;
public static DBConnection Instance()
{
if (_instance == null)
_instance = new DBConnection();
return _instance;
}
and rather than use DBConnection.Instance, just use new DBConnection();
And change:
public MySqlConnection Connection
{
get { return connection; }
}
to:
public MySqlConnection Connection
{
get {
IsConnect();
return connection; }
}
and change:
public bool IsConnect()
{
bool result = true;
if (Connection == null)
to:
public bool IsConnect()
{
bool result = true;
if (connection == null)
I see you are using singletne pattern for DBConnection this is not a good idea.
private static DBConnection _instance = null;
public static DBConnection Instance()
{
if (_instance == null)
_instance = new DBConnection();
return _instance;
}
You might want to check this answer out for more information: https://stackoverflow.com/a/814606/8143718
As per #mjwills' response, the DB interface script I'd swiped was quite funky and only allowed one instance at a time.
Working DB Interface
using MySql.Data.MySqlClient;
using System;
namespace vmcmod
{
public class DBConnection
{
public DBConnection()
{
}
public string Password { get; set; }
private MySqlConnection connection = null;
public MySqlConnection Connection
{
get
{
IsConnect();
return connection;
}
}
public bool IsConnect()
{
bool result = true;
if (connection == null)
{
string connString = "Server=...; Port=...; Database=...; Uid=...; Pwd=...;";
connection = new MySqlConnection(connString);
try
{
connection.Open();
Utils.consoleLog("Connected to repository.", 4);
result = true;
}
catch (Exception e)
{
Utils.consoleLog("Error occured while connecting to repository.", 3);
Utils.consoleLog("MySQL Exception: "+e,5);
result = false;
}
}
return result;
}
public void Close()
{
connection.Close();
connection = null;
}
}
}

MySQL OdbcCommand commands sometimes hangs?

I am running a loop in C# that reads a file and make updates to the MySQL database with MySQL ODBC 5.1 driver in a Windows 8 64-bit environment.
The operations is simple
Count +1
See if file exists
Load XML file(XDocument)
Fetch data from XDocument
Open ODBCConnection
Run a couple of Stored Procedures against the MySQL database to store data
Close ODBCConnection
The problem is that after a while it will hang on for example a OdbcCommand.ExecuteNonQuery. It is not always the same SP that it will hang on?
This is a real problem, I need to loop 60 000 files but it only last around 1000 at a time.
Edit 1:
The problem seemse to accure here hever time :
public bool addPublisherToGame(int inPublisherId, int inGameId)
{
string sqlStr;
OdbcCommand commandObj;
try
{
sqlStr = "INSERT INTO games_publisher_binder (gameId, publisherId) VALUE(?,?)";
commandObj = new OdbcCommand(sqlStr, mainConnection);
commandObj.Parameters.Add("#gameId", OdbcType.Int).Value = inGameId;
commandObj.Parameters.Add("#publisherId", OdbcType.Int).Value = inPublisherId;
if (Convert.ToInt32(executeNonQuery(commandObj)) > 0)
return true;
else
return false;
}
catch (Exception ex)
{
throw (loggErrorMessage(this.ToString(), "addPublisherToGame", ex, -1, "", ""));
}
finally
{
}
}
protected object executeNonQuery(OdbcCommand inCommandObj)
{
try
{
//FileStream file = new FileStream("d:\\test.txt", FileMode.Append, FileAccess.Write);
//System.IO.StreamWriter stream = new System.IO.StreamWriter(file);
//stream.WriteLine(DateTime.Now.ToString() + " - " + inCommandObj.CommandText);
//stream.Close();
//file.Close();
//mainConnection.Open();
return inCommandObj.ExecuteNonQuery();
}
catch (Exception ex)
{
throw (ex);
}
}
I can see that the in parameters is correct
The open and close of the connection is done in a top method for ever loop (with finally).
Edit 2:
This is the method that will extract the information and save to database :
public Boolean addBoardgameToDatabase(XElement boardgame, GameFactory gameFactory)
{
int incomingGameId = -1;
XElement tmpElement;
string primaryName = string.Empty;
List<string> names = new List<string>();
GameStorage externalGameStorage;
int retry = 3;
try
{
if (boardgame.FirstAttribute != null &&
boardgame.FirstAttribute.Value != null)
{
while (retry > -1)
{
try
{
incomingGameId = int.Parse(boardgame.FirstAttribute.Value);
#region Find primary name
tmpElement = boardgame.Elements("name").Where(c => c.Attribute("primary") != null).FirstOrDefault(a => a.Attribute("primary").Value.Equals("true"));
if (tmpElement != null)
primaryName = tmpElement.Value;
else
return false;
#endregion
externalGameStorage = new GameStorage(incomingGameId,
primaryName,
string.Empty,
getDateTime("1/1/" + boardgame.Element("yearpublished").Value),
getInteger(boardgame.Element("minplayers").Value),
getInteger(boardgame.Element("maxplayers").Value),
boardgame.Element("playingtime").Value,
0, 0, false);
gameFactory.updateGame(externalGameStorage);
gameFactory.updateGameGrade(incomingGameId);
gameFactory.removeDesignersFromGame(externalGameStorage.id);
foreach (XElement designer in boardgame.Elements("boardgamedesigner"))
{
gameFactory.updateDesigner(int.Parse(designer.FirstAttribute.Value), designer.Value);
gameFactory.addDesignerToGame(int.Parse(designer.FirstAttribute.Value), externalGameStorage.id);
}
gameFactory.removePublishersFromGame(externalGameStorage.id);
foreach (XElement publisher in boardgame.Elements("boardgamepublisher"))
{
gameFactory.updatePublisher(int.Parse(publisher.FirstAttribute.Value), publisher.Value, string.Empty);
gameFactory.addPublisherToGame(int.Parse(publisher.FirstAttribute.Value), externalGameStorage.id);
}
foreach (XElement element in boardgame.Elements("name").Where(c => c.Attribute("primary") == null))
names.Add(element.Value);
gameFactory.removeGameNames(incomingGameId);
foreach (string name in names)
if (name != null && name.Length > 0)
gameFactory.addGameName(incomingGameId, name);
return true;
}
catch (Exception)
{
retry--;
if (retry < 0)
return false;
}
}
}
return false;
}
catch (Exception ex)
{
throw (new Exception(this.ToString() + ".addBoardgameToDatabase : " + ex.Message, ex));
}
}
And then we got one step higher, the method that will trigger addBoardgameToDatabase :
private void StartThreadToHandleXmlFile(int gameId)
{
FileInfo fileInfo;
XDocument xmlDoc;
Boolean gameAdded = false;
GameFactory gameFactory = new GameFactory();
try
{
fileInfo = new FileInfo(_directory + "\\" + gameId.ToString() + ".xml");
if (fileInfo.Exists)
{
xmlDoc = XDocument.Load(fileInfo.FullName);
if (addBoardgameToDatabase(xmlDoc.Element("boardgames").Element("boardgame"), gameFactory))
{
gameAdded = true;
fileInfo.Delete();
}
else
return;
}
if (!gameAdded)
{
gameFactory.InactivateGame(gameId);
fileInfo.Delete();
}
}
catch (Exception)
{ throw; }
finally
{
if(gameFactory != null)
gameFactory.CloseConnection();
}
}
And then finally the top level :
public void UpdateGames(string directory)
{
DirectoryInfo dirInfo;
FileInfo fileInfo;
Thread thread;
int gameIdToStartOn = 1;
dirInfo = new DirectoryInfo(directory);
if(dirInfo.Exists)
{
_directory = directory;
fileInfo = dirInfo.GetFiles("*.xml").OrderBy(c=> int.Parse(c.Name.Replace(".xml",""))).FirstOrDefault();
gameIdToStartOn = int.Parse(fileInfo.Name.Replace(".xml", ""));
for (int gameId = gameIdToStartOn; gameId < 500000; gameId++)
{
try
{ StartThreadToHandleXmlFile(gameId); }
catch(Exception){}
}
}
}
Use SQL connection pooling by adding "Pooling=true" to your connectionstring.
Make sure you properly close the connection AND the file.
You can create one large query and execute it only once, I think it is a lot faster then 60.000 loose queries!
Can you show a bit of your code?

Categories

Resources