I'm polling a site and updating my datasource (SQLite table). The table gets updated correctly right after the poll.
An XPCollection is associated with the table and the XPCollection is used as the DataSource for the Grid Control.
My problem is: the Grid's data is not updated. I must open and close the application to see he new data reflected in the Grid.
I have tried all combinations of removing data source, refreshing datasource, but nothing seems to work.
Below is my code for polling and refreshing the Grid,
private async void WaitForXSeconds()
{
for (int i = 0; i < 100; i++)
{
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(60));
// do something after x seconds!
// Updates the DB with new/modified data
LoadDailyButton_Click(null, null);
BestGrid.DataSource = null;
BestGrid.DataSource = BestCollection;
string starttime = System.DateTime.Now.ToString();
CycleResultsListBox.Items.Add("Cycle Started : " + starttime.ToString());
}
}
Here is a partial snippet of what my class look like:
public class BestData : XPLiteObject
{
private int id;
[Key(true)]
public int Id
{
get { return id; }
set
{
id = value;
}
}
private DateTime gameDate;
public DateTime GameDate
{
get { return gameDate; }
set
{
gameDate = value;
}
}
private string hometeamName;
public string HomeTeamName
{
get { return hometeamName; }
set
{
hometeamName = value;
}
}
Any help would be appreciated, this one is causing headaches.
Did you try to call
BestGrid.DataBind(); after BestGrid.DataSource = xxx
private async void WaitForXSeconds()
{
for (int i = 0; i < 100; i++)
{
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(60));
// do something after x seconds!
// Updates the DB with new/modified data
LoadDailyButton_Click(null, null);
BestGrid.DataSource = null;
BestGrid.DataSource = BestCollection;
Bestgrid.DataBind();
string starttime = System.DateTime.Now.ToString();
CycleResultsListBox.Items.Add("Cycle Started : " + starttime.ToString());
}
}
Édit 1
gridControl1.BeginUpdate();
try
{
gridView1.Columns.Clear();
gridControl1.DataSource = null;
gridControl1.DataSource = <newDataSource>;
}
finally
{
gridControl1.EndUpdate();
}
For you:
for (int i = 0; i< 100; i++)
{
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(60));
// do something after x seconds!
// Updates the DB with new/modified data
LoadDailyButton_Click(null, null);
gridControl1.BeginUpdate();
BestGrid.DataSource = null;
BestGrid.DataSource = BestCollection;
gridControl1.EndUpdate();
string starttime = System.DateTime.Now.ToString();
CycleResultsListBox.Items.Add("Cycle Started : " + starttime.ToString());
}
The following code has fixed my problem.
private async void WaitForXSeconds()
{
for (int i = 0; i < 100; i++)
{
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(300));
// do something after x seconds!
// Updates the DB with new/modified data
LoadDailyButton_Click(null, null);
gridView2.CollapseAllDetails();
BestGrid.DataSource = null;
session1.DropIdentityMap();
BestCollection.Reload();
BestGrid.DataSource = BestCollection;
string starttime = System.DateTime.Now.ToString();
CycleResultsListBox.Items.Add("Cycle Started : " + starttime.ToString());
}
}
Here is the code I use to save the data;
using (var uow = new UnitOfWork(xsession.DataLayer))
{
BestData getSingleRec = new XPCollection<BestData>(uow, CriteriaOperator.Parse("[HomeTeamName]=? AND [GameDate]=?", tempStr5.ToString(), Convert.ToDateTime(gameDate))).FirstOrDefault();
getSingleRec.awayR = Convert.ToInt16(tempStr7);
getSingleRec.homeR = Convert.ToInt16(tempStr8);
getSingleRec.awayML = tempStr2;
getSingleRec.homeML = tempStr3;
getSingleRec.Save();
uow.CommitChanges();
}
Related
How to read whole row and save it to variable? I know what type is stored there (custom Employee type).
I have tried doing it kind of manually.
private async void AddEmployee()
{
var context = new NorthwindContext();
int selectedRowCount = EmpMgmtDataGridView.Rows.GetRowCount(DataGridViewElementStates.Selected);
if (selectedRowCount > 0)
{
for (int i = 0; i < selectedRowCount; i++)
{
var employeeToAdd = new Employees();
employeeToAdd.FirstName = EmpMgmtDataGridView[1, i].ToString();
employeeToAdd.LastName = EmpMgmtDataGridView[2, i].ToString();
await context.AddAsync(employeeToAdd);
await context.SaveChangesAsync();
}
}
}
But it ends with
SqlException: String or binary data would be truncated.
The statement has been terminated.
at SaveChanges.
I'm trying to send it into database, but i know how to do it, i just can't get it from DataGridView.
Edit
Made an upgrade but it ends with identical error.
private async void AddEmployee()
{
var context = new NorthwindContext();
int selectedRowCount = EmpMgmtDataGridView.Rows.GetRowCount(DataGridViewElementStates.Selected);
var rows = EmpMgmtDataGridView.SelectedRows;
if (selectedRowCount > 0)
{
for (int i = 0; i < selectedRowCount; i++)
{
var employeeToAdd = new Employees();
employeeToAdd.LastName = rows[i].Cells[1].ToString();
employeeToAdd.FirstName = rows[i].Cells[2].ToString();
await context.AddAsync(employeeToAdd);
await context.SaveChangesAsync();
}
}
}
Make sure you are actually getting the Value of the cell rather than the cell object itself:
employeeToAdd.LastName = rows[i].Cells[1].Value.ToString();
employeeToAdd.FirstName = rows[i].Cells[2].Value.ToString();
I have to store multiple xml files data into a single list of IEnumerable<SyncEntity>, but I don't get exact result as expected. Below is my sample code.
public IEnumerable<SyncEntity> GetUpdatedItemsOfType(DateTime? fromDate, string entityName, List<string> fieldsToRetrieve)
{
ConnLogger.WriteInfo("Dooors SyncConnector", "Run DOORS DXL for List of Getupdateditems of type ");
try
{
var dxlInput = $"{TmpRootFolder};{entityName};{fromDate.ToString()};{string.Join(",", fieldsToRetrieve)};{fieldsToRetrieve.Count.ToString()}";
string dxlPath = GetDxl("GetUpdatedItemsOfType.dxl");
//ActivateAsync(() =>
//{
// DoorsHandle.result = dxlInput;
// DoorsHandle.runFile(dxlPath);
//});
_doorsHandle.result = dxlInput;
_doorsHandle.runFile(dxlPath);
return GetUpdatedItemsOfTypePagination(TmpRootFolder);
}
catch (Exception ex)
{
ConnLogger.WriteException("Doors SyncConnector", ex, "Failed to get list of updateditems of type");
throw;
}
}
The above GetUpdatedItemsOfType(DateTime? fromDate, string entityName, List<string> fieldsToRetrieve) method is where I start one process of doors.
private IEnumerable<SyncEntity> GetUpdatedItemsOfTypePagination(string folderPath)
{
int currentPage = 1;
string finishFilePath = Path.Combine(folderPath, "GetUpdateItemsOfType_Finish.xml");
while (true)
{
string xmlFileFullPath = Path.Combine(folderPath, $"GetUpdateItemsOfType{currentPage}.xml");
bool pageReadCompleted = false;
for (int i = 0; i < 1000; i++) //wait max time of 1,000*0.1 = 100 seconds
{
if (!File.Exists(xmlFileFullPath))
{
if (File.Exists(finishFilePath))
{
yield break;
}
Thread.Sleep(TimeSpan.FromSeconds(0.1));
continue;
}
List<SyncEntity> pageItems = GetUpdatedItemsPage(xmlFileFullPath);
pageReadCompleted = true;
foreach (var syncEntity in pageItems)
{
yield return syncEntity;
}
break;
}
if (!pageReadCompleted)
{
throw new ApplicationException("Timeout reached for GetUpdatedItems method...");
}
currentPage++;
}
}
The above GetUpdatedItemsOfTypePagination(string folderPath) method checks the xml files in given folder.
private List<SyncEntity> GetUpdatedItemsPage(string xmlFilePath)
{
List<FileAttachment> fileAttachment=new List<FileAttachment>();
var xmlData = GenericSerializer.XmlDeSerialize<UpdatedItemsResult>(File.ReadAllText(xmlFilePath));
return xmlData.Items.Select(field => new SyncEntity
{
Name = field.ObjectName,
Id = field.Id,
Modified = Convert.ToDateTime(field.LastModifiedOn),
Fields = field.Attributes.Select(filed => new EntityField
{
Name = filed.Name,
Type = MetadataManager.FromDoorsDataType(filed.Type),
Value = fileAttachment
}).ToList()
}).ToList();
//copy here relevant code from the Execute method
}
The above GetUpdatedItemsPage(string xmlFilePath) method is the relevant code to deserialize the xml data.
I am using Data Grid to show passbook balance. I have done everything I'm unable to get the balance value in the respective column.
private void dgview2_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
int credit1, debit1;
int balance = new int();
if (int.TryParse(dgview2.Rows[e.RowIndex].Cells["debit"].Value.ToString(),
out debit1) && int.TryParse(dgview2.Rows[e.RowIndex].Cells["credit"].Value.ToString(),
out credit1) && int.TryParse(dgview2.Rows[e.RowIndex].Cells["balance"].Value.ToString(),
out balance))
{
balance = balance + credit1 - debit1;
dgview2.Rows[e.RowIndex].Cells["balance"].Value = balance.ToString();
}
}
Vfp9sp2 Application output
here is the code which i am useing to populate grid
private void fill_div()
{
var com = new MySqlCommand("Select *From shtrn where mem_no ='" + textBox1.Text + "' order by tdate ", con_db.con);
var dr = com.ExecuteReader();
try
{
dgview2.Rows.Clear();
while (dr.Read())
{
var n = dgview2.Rows.Add();
dgview2.Rows[n].Cells[0].Value = Convert.ToDateTime(dr["tdate"].ToString());
dgview2.Rows[n].Cells[1].Value = dr["particular"].ToString();
dgview2.Rows[n].Cells[2].Value = dr["trmode"].ToString();
dgview2.Rows[n].Cells[3].Value = dr["debit"].ToString();
dgview2.Rows[n].Cells[4].Value = dr["credit"].ToString();
dgview2.Rows[n].Cells[5].Value = dr["balance"].ToString();
dgview2.FirstDisplayedScrollingRowIndex = n;
dgview2.CurrentCell = dgview2.Rows[n].Cells[0];
UpdateBalance();
}
{
dr.Close();
}
}
catch (FormatException)
{
MessageBox.Show("No Records Found ");
}
}
The reason code does not work is that grid is made read only, therefore code specified in the event handler (dgview2_CellEndEdit) is not triggered.
Ideally you should be making balance calculations before updating the grid, but as a quick workaround you can move the code to a private method like this:
private void UpdateBalance()
{
for (int i = 0; i < dgview2.Rows.Count; i++)
{
int credit1, debit1, balance;
if (int.TryParse(dgview2.Rows[i].Cells[3].Value.ToString(),
out debit1) && int.TryParse(dgview2.Rows[i].Cells[4].Value.ToString(),
out credit1) && int.TryParse(dgview2.Rows[i].Cells[5].Value.ToString(),
out balance))
{
balance = balance + credit1 - debit1;
dgview2.Rows[i].Cells[5].Value = balance.ToString();
}
}
}
Then call this method after you finished populating the grid:
UpdateBalance();
The method iterates over each row and updates balance cells using the same logic.
[Edit for update code]
Instead of above, you can perform calculation in your update logic as below:
while (dr.Read())
{
var n = dgview2.Rows.Add();
dgview2.Rows[n].Cells[0].Value = Convert.ToDateTime(dr["tdate"].ToString());
dgview2.Rows[n].Cells[1].Value = dr["particular"].ToString();
dgview2.Rows[n].Cells[2].Value = dr["trmode"].ToString();
dgview2.Rows[n].Cells[3].Value = dr["debit"].ToString();
dgview2.Rows[n].Cells[4].Value = dr["credit"].ToString();
dgview2.Rows[n].Cells[5].Value = dr["balance"].ToString();
int credit1, debit1, balance;
if (int.TryParse(dr["debit"].ToString(),
out debit1) && int.TryParse(dr["credit"].ToString(),
out credit1) && int.TryParse(dr["balance"].ToString(),
out balance))
{
dgview2.Rows[n].Cells[5].Value = balance + credit1 - debit1;
}
dgview2.FirstDisplayedScrollingRowIndex = n;
dgview2.CurrentCell = dgview2.Rows[n].Cells[0];
}
I have this code to load and count data from API server;
class TestNetWork
{
private Task taskFillPicker;
private List<CityItemDB> itemsCity;
private CustomPicker cpCity;
public async Task FillPicker()
{
try {
JObject res = await SuperFUNC.GET_CITY_ACTIVE_SENDER();
if(res == null){
//null
}else{
string message = res["message"].ToString();
if(message.Equals("Success")){
itemsCity.Clear();
cpCity.Items.Clear();
JArray data = (JArray)res["data"];
int count = data.Count;
for (int i = 0; i < count; i++) {
CityItemDB node = new CityItemDB();
node.cityId = Int32.Parse(data[i]["cityId"].ToString());
node.cityName = data[i]["cityName"].ToString();
itemsCity.Add(node);
cpCity.Items.Add(node.ToString());
}
}else{
//null
}
}
} catch (Exception ex) {
Debug.WriteLine (TAG + " : " + ex.StackTrace);
}
}
public TestNetWork()
{
this.itemsCity = new List<CityItemDB> ();
this.cpCity = new CustomPicker {
HeightRequest = 40,
TextColor = Color.FromHex("#5a5a5a"),
Title = "City Choose",
};
taskFillPicker = FillPicker ();
Debug.WriteLine (COUNT + " : " + itemsCity.Count);
}
}
But console print me COUNT : 0, I'm sure code get and parse json from internet is correct, picker show full data but List<CityItemDB> itemsCity count 0.
Thank for read, sorry my english not good!
You need to await the task, otherwise execution might continue before FillPicker has completed:
taskFillPicker = await FillPicker ();
As this code is in a constructor where await is not possible, I suggest moving it to a separate async method:
public async Task Init()
{
taskFillPicker = await FillPicker ();
Debug.WriteLine (COUNT + " : " + itemsCity.Count);
}
You have to write a little bit more code to construct the object now:
var n = new TestNetWork();
await n.Init();
Parallel.ForEach keeps on running and my program does not end. I am unable to trace where it goes after the first iteration. My guess is that gets a deadlock and keeps on doing context switching.
private void ReadInputFile()
{
var collection = new ConcurrentBag<PropertyRecord>();
var lines = System.IO.File.ReadLines(InputFileName);
int i = 0;
int RecordsCount = lines.Count();
Parallel.ForEach(lines, line =>
{
if (string.IsNullOrWhiteSpace(line))
{
return;
}
var tokens = line.Split(',');
var postalCode = tokens[0];
var country = tokens.Length > 1 ? tokens[1] : "england";
SetLabelNotifyTwoText(
string.Format(
"Reading PostCode {0} out of {1}"
i,
lines.Length));
var tempRecord = GetAllAddesses(postalCode, country);
if (tempRecord != null)
{
foreach (PropertyRecord r in tempRecord)
{
collection.Add(r);
}
}
});
}
private List<PropertyRecord> GetAllAddesses(
string postalCode,
string country = "england")
{
SetLabelNotifyText("");
progressBar1.Value = 0;
progressBar1.Update();
var records = new List<PropertyRecord>();
using (WebClient w = new WebClient())
{
var url = CreateUrl(postalCode, country);
var document = w.DownloadString(url);
var pagesCount = GetPagesCount(document);
if (pagesCount == null)
{
return null;
}
for (int i = 0; i < pagesCount; i++)
{
SetLabelNotifyText(
string.Format(
"Reading Page {0} out of {1}",
i,
pagesCount - 1));
url = CreateUrl(postalcode,country, i);
document = w.DownloadString(url);
var collection = Regex.Matches(
document,
"<div class=\"soldDetails\">(.|\\n|\\r)*?class=" +
"\"soldAddress\".*?>(?<address>.*?)(</a>|</div>)" +
"(.|\\n|\\r)*?class=\\\"noBed\\\">(?<noBed>.*?)" +
"</td>|</tbody>");
foreach (var match in collection)
{
var r = new PropertyRecord();
var bedroomCount = match.Groups["noBed"].Value;
if(!string.IsNullOrEmpty(bedroomCount))
{
r.BedroomCount = bedroomCount;
}
else
{
r.BedroomCount = "-1";
}
r.address = match.Groups["address"].Value;
var line = string.Format(
"\"{0}\",{1}",
r.address
r.BedroomCount);
OutputLines.Add(line);
Records.Add(r);
}
}
}
return Records;
}
It runs fine without Parallel.ForEach, but using Parallel.ForEach is in requirements.
I have debugged it and after returning from GetAllAdresses-method first time, Step Next button halts and it just keep on debugging in the background. It doesn't come back on any bookmark I have placed.
As you said in comments, your SetLabelNotifyText and SetLabelNotifyTwoText methods calls Control.Invoke.
For Control.Invoke to work, Main thread has to be free, but in your case you seem to block the main thread by invoking Parallel.ForEach in it.
Here is a minimal reproduction:
private void button1_Click(object sender, EventArgs e)
{
Parallel.ForEach(Enumerable.Range(1, 100), (i) =>
{
Thread.Sleep(10);//Simulate some work
this.Invoke(new Action(() => SetText(i)));
});
}
private void SetText(int i)
{
textBox1.Text = i.ToString();
}
Main thread waits for Parallel.ForEach and worker threads waits for Main thread, and thus results in deadlock.
How to fix: Don't use Invoke simply use BeginInvoke or don't block the MainThread.
If this isn't the case post sscce, that will be helpful for us
Change your code like this, to use async and await. This is the modern alternative to using BeginInvoke and other asynchronous code models.
private async Task ReadInputFile()
{
var collection = new ConcurrentBag<PropertyRecord>();
var lines = System.IO.File.ReadLines(InputFileName);
int i = 0;
int RecordsCount = lines.Count();
Parallel.ForEach(lines, line =>
{
if (string.IsNullOrWhiteSpace(line))
{
return;
}
var tokens = line.Split(',');
var postalCode = tokens[0];
var country = tokens.Length > 1 ? tokens[1] : "england";
SetLabelNotifyTwoText(
string.Format(
"Reading PostCode {0} out of {1}"
i,
lines.Length));
var tempRecord = await GetAllAddesses(postalCode, country);
if (tempRecord != null)
{
foreach (PropertyRecord r in tempRecord)
{
collection.Add(r);
}
}
});
}
private async Task<List<PropertyRecord>> GetAllAddesses(
string postalCode,
string country = "england")
{
SetLabelNotifyText("");
progressBar1.Value = 0;
progressBar1.Update();
var records = new List<PropertyRecord>();
using (WebClient w = new WebClient())
{
var url = CreateUrl(postalCode, country);
var document = await w.DownloadStringTaskAsync(url);
var pagesCount = GetPagesCount(document);
if (pagesCount == null)
{
return null;
}
for (int i = 0; i < pagesCount; i++)
{
SetLabelNotifyText(
string.Format(
"Reading Page {0} out of {1}",
i,
pagesCount - 1));
url = CreateUrl(postalcode,country, i);
document = await w.DownloadStringTaskAsync(url);
var collection = Regex.Matches(
document,
"<div class=\"soldDetails\">(.|\\n|\\r)*?class=" +
"\"soldAddress\".*?>(?<address>.*?)(</a>|</div>)" +
"(.|\\n|\\r)*?class=\\\"noBed\\\">(?<noBed>.*?)" +
"</td>|</tbody>");
foreach (var match in collection)
{
var r = new PropertyRecord();
var bedroomCount = match.Groups["noBed"].Value;
if(!string.IsNullOrEmpty(bedroomCount))
{
r.BedroomCount = bedroomCount;
}
else
{
r.BedroomCount = "-1";
}
r.address = match.Groups["address"].Value;
var line = string.Format(
"\"{0}\",{1}",
r.address
r.BedroomCount);
OutputLines.Add(line);
Records.Add(r);
}
}
}
return Records;
}
Then call it like this
ReadInputFile.Wait();
or, even better, is the caller is async,
await ReadInputFile();