ADO.net Question - How can I update a column in a Row of a DataTable with RowChanged without triggering infinite loop? - ado.net

How can I update the column value (programmatically) in a Row of a DataTable via use of the RowChanged event, without triggering infinite loop? (which I currently get)
Note I do not want to use the DataColumn.Expression property.
For example the following gives me a recursive loop and stack overflow error:
DataColumn dc = new DataColumn("OverallSize", typeof(long));
DT_Webfiles.Columns.Add(dc);
DT_Webfiles.RowChanged += new DataRowChangeEventHandler(DT_Row_Changed);
private static void DT_Row_Changed(object sender, DataRowChangeEventArgs e)
{
Console.Out.WriteLine("DT_Row_Changed - Size = " + e.Row["OverallSize"]);
e.Row["OverallSize"] = e.Row["OverallSize"] ?? 0;
e.Row["OverallSize"] = (long)e.Row["OverallSize"] + 1;
}
thanks
PS. In fact using the RowChanging event (rather than RowChanged) makes sense to me (i.e. change the value before it saves so to speak) however when I try this I get a "Cannot change a proposed value in the RowChanging event" at the following line in the handler:
e.Row["OverallSize"] = e.Row["OverallSize"] ?? 0;

You could unsubscribe when within the event handler, though that would make your code not thread-safe.
DataColumn dc = new DataColumn("OverallSize", typeof(long));
DT_Webfiles.Columns.Add(dc);
DT_Webfiles.RowChanged += new DataRowChangeEventHandler(DT_Row_Changed);
private static void DT_Row_Changed(object sender, DataRowChangeEventArgs e)
{
e.RowChanged -= new DataRowChangeEventHandler(DT_Row_Changed);
Console.Out.WriteLine("DT_Row_Changed - Size = " + e.Row["OverallSize"]);
e.Row["OverallSize"] = e.Row["OverallSize"] ?? 0;
e.Row["OverallSize"] = (long)e.Row["OverallSize"] + 1;
e.RowChanged += new DataRowChangeEventHandler(DT_Row_Changed);
}

Try with this
e.Row.Table.RowChanged -= new DataRowChangeEventHandler(DT_Row_Changed);
And
e.Row.Table.RowChanged += new DataRowChangeEventHandler(DT_Row_Changed);

Related

How to use doOnNext, doOnSubscribe and doOnComplete?

New to RxJava2/RxAndroid and Android development, but am pretty familiar with Java.
However, I've ran into quite a roadblock when trying to "optimize" and be able to update the UI between a bunch of calls to the same resource.
My code is as follows:
private int batch = 0;
private int totalBatches = 0;
private List<ItemInfo> apiRetItems = new ArrayList<>();
private Observable<ItemInfo[]> apiGetItems(int[] ids) {
int batchSize = 100;
return Observable.create(emitter -> {
int[] idpart = new int[0];
for(int i = 0; i < ids.length; i += batchSize) {
batch++;
idpart = Arrays.copyOfRange(ids, i, Math.min(ids.length, i+batchSize));
ItemInfo[] items = client.items().get(idpart);
emitter.onNext(items);
}
emitter.onComplete();
}).doOnSubscribe( __ -> {
Log.d("GW2DB", "apiGetItems subscribed to with " + ids.length + " ids.");
totalBatches = (int)Math.ceil(ids.length / batchSize);
progressbarUpdate(0, totalBatches);
}).doOnNext(items -> {
Log.d("GW2DB", batch + " batches of " + totalBatches + " batches completed.");
progressbarUpdate(batch, totalBatches);
}).doOnComplete( () -> {
Log.d("GW2DB", "Fetching items completed!");
progressbarReset();
});
}
If I remove the doOnSubscribe, doOnNext and doOnComplete I get no errors in Android Studio, but if I use any of them I get Incompatible types. Required: Observable<[...].ItemInfo[]>. Found: Observable<java.lang.Object>
I'm using RxAndroid 2.1.1 and RxJava 2.2.16.
Any ideas?
Since you are adding a chain of method calls, the compiler is just unable to correctly guess the type for the generic parameter in Observable.create. You can set it explicitly using Observable.<ItemInfo[]>create(...).

Why my add Event listener doesn't work correctly?

Here is my code.
var _this = this;
var i = 0;
var object;
for (i=1 ; i <5 ; i++){
object = new lib.A ();
object.x = 50 * i;
object.y = 100;
_this.addChild (object);
object.on ("tick" , position , true)
}
function position(){
object.y += 1;
}
I have an object in the library and create and add to stage 4 number.
I want to move down all object with the addEventListener (tick), but it moves last object.
You need to reference the clicked object. In your code, the object variable changes in your for-loop, so at the end it is the last known value. Instead use the clicked target from the event (passed in the click handler):
function position(event){
event.currentTarget.y += 1;
}
Cheers,
I hope you have a stage somewhere in your code to depict the canvas, as in:
stage = new createjs.Stage("gameCanvas");
I think you're missing stage.update(event) as in:
function position(event){
//....update the poositions
stage.update(event);
}

DataProvider in TestNG to pass data from excel

I started learning Selenium2 (WebDriver) with Eclipse and TestNG. I have a question about DataProvider. I have a login page having user, password and login button for example. I have written a test in TestNG. I have used pageobject for UI objects (have separate class) and actual test in another class.
Here glogin is a class and login is the function where finding elements and sending keys is done and this is called in another class gtest(which is main test) which has TestNG annotations.
I access that class in main script which will take values.
#test(Dataprovide = "test")
public void glogin(String user, String pass)
{
glogin log1 = new login;
log1.login(user,pass);
}
I have the following excel sheet
user pass
John Smith
Carson Black
Carla ck23
test test4
When I use dataprovider and get data from the excel sheet as array and use it in Test then the following error is displayed:
org.testng.TestNGException:
The data provider is trying to pass 4 parameters but the method plus.gmail#glogin takes 2
at org.testng.internal.Invoker.injectParameters(Invoker.java:1337)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1225)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:128)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at org.testng.TestRunner.privateRun(TestRunner.java:767)
at org.testng.TestRunner.run(TestRunner.java:617)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
at org.testng.SuiteRunner.run(SuiteRunner.java:240)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1203)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1128)
at org.testng.TestNG.run(TestNG.java:1036)
at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:111)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:204)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:175)
Any help is really appreciated.
Here is code for method annotated with Dataprovider and
#DataProvider(name="test")
public Object[][] createdata1()throws Exception
{
Object[][] retobj = getexcel();
return retobj;
}
private String[][] getexcel() throws Exception
{
// TODO Auto-generated method stub
String[][] tabarray = null;
try {
Workbook wb1 = Workbook.getWorkbook(new
File("F:/testdata.xls"));
Sheet sheet = wb1.getSheet("userlogin");
Cell tablestart = sheet.findCell("login");
int startrow = tablestart.getRow();
int startcol = tablestart.getColumn();
Cell tableend = sheet.findCell("login",startcol+1,startrow+1,
100, 64000, false);
int endrow = tableend.getRow();
int endcol = tableend.getColumn();
System.out.println("startRow="+startrow+", endRow="+endrow+",
" + "startCol="+startcol+", endCol="+endcol);
tabarray = new String[endrow - startrow + 1][endcol -
startcol + 1];
int ci = 0;
for(int i = startrow +1 ;i<endrow;i++,ci++)
{
int cj = 0;
for(int j = startcol + 1;j<endcol;j++,cj++)
{
tabarray[ci][cj] = sheet.getCell(j,
i).getContents();
System.out.println(tabarray[ci][cj]);
}
}
} catch (BiffException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return tabarray;
}
test(Dataprovider = "test")
public void glogins(String user, String pass)
{
glogin log1 = new glogin(driver);
log1.login(user,pass);
}
When I executed the test, I received data from excel as
john
smith
carson
Black
carla
ck23
test
test4
as output
Isn't the error message self-explanatory?
The data provider is trying to pass 4 parameters but the method plus.gmail#glogin takes 2
Use a debugger and figure out why your data provider is returning 4 parameters instead of just 2.
Use
tabarray = new String[endrow - 1][endcol - 1]; instead of //tabarray = new String[endrow - startrow + 1][endcol - startcol + 1];
Because you intended to return only 2*2 array
Replace the line
tabarray = new String[endrow - startrow + 1][endcol - startcol + 1];
with
tabarray = new String[endrow - startrow - 1][endcol - startcol - 1];
I agree with the response posted by Kalyan; the reason being the first and last column of the data provider excel sheet is also counted in as arguments / parameters by the function; therefore please use tabArray=new String[endRow-startRow-1][endCol-startCol-1]; Hope this helps and happy testing...

Is ObjectContext.SaveChanges ACIDIC?

As the title suggests, Is the following code acidic, e.g. if I call SaveChanges, will all the Product.Add INSERT statements be executed (or rolled back if there is an error).
using(DBEntities ctx = new DBEntities())
{
for(int i = 0; i < 10; i++)
{
ctx.Products.Add(new Product("Product " + (i + 1)));
}
ctx.SaveChanges();
}
MSDN states:
SaveChanges operates within a transaction. SaveChanges will roll back
that transaction and throw an exception if any of the dirty
ObjectStateEntry objects cannot be persisted.
However looking at the profiler, this doesn't seem to be the case. Am I required to wrap the block with TransactionScope?
using(DBEntities ctx = new DBEntities())
{
for(int i = 0; i < 10; i++)
{
ctx.Products.Add(new Product("Product " + (i + 1)));
}
ctx.SaveChanges();
}
This SaveChanges() call will be in a transaction automatically. You won't have to wrap it under a new transactionscope.

Ajax Popupcontrolextender issues

I have a bizarre problem. I have followed the example here (http://www.4guysfromrolla.com/articles/071107-1.aspx) to display an ajax popup, but it is not working properly.
The problem I have is that the image attributes are not set properly, I checked with Firebug and this is what I get on page 1 after load.
<img src="StyleSheets/magglass.jpg" id="mainContent_TheGrid_MagGlass_0">
Now the bizarre, if I go to page 2, the onmouseover event is set properly for all images and if I come back to page 1, it is set properly too, e.g.
<img src="StyleSheets/magglass.jpg" onmouseover="$find('pce0').showPopup(); " id="mainContent_TheGrid_MagGlass_0">
I stepped through the code and confirmed that the rowcreated event is firing for my grid, for each row
Any Ideas?
My code is slightly different to the example, see below
protected void TheGrid_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// Programmatically reference the PopupControlExtender
PopupControlExtender pce = e.Row.FindControl("TheGrid_PopupControlExtender") as PopupControlExtender;
// Set the BehaviorID
string behaviorID = string.Concat("pce", e.Row.RowIndex);
pce.BehaviorID = behaviorID;
// Programmatically reference the Image control
Image i = (Image)e.Row.Cells[0].FindControl("MagGlass");
// Add the client-side attributes (onmouseover & onmouseout)
string OnMouseOverScript = string.Format("$find('{0}').showPopup(); ", behaviorID);
i.Attributes.Add("onmouseover", OnMouseOverScript);
}
}
The GetDynamicContent Method is below, which adds the hidepopup method.
[System.Web.Services.WebMethodAttribute(), System.Web.Script.Services.ScriptMethodAttribute()]
public static string GetDynamicContent(string contextKey)
{
GridView MyGrid = (GridView)HttpContext.Current.Session["TheGrid"];
var MyVar = from GridViewRow MyRow in MyGrid.Rows
where MyRow.Cells[MyRow.Cells.Count - 1].Text == contextKey
select MyRow;
//This is the selected row by the user
GridViewRow MyGridRow = MyVar.SingleOrDefault();
//MyGridRow.Cells[3].Text is the log entry.
string MyTable = #"<table class=""PopUpTable""><tr><td><textarea class=""textarea"">"
+ MyGridRow.Cells[3].Text + "</textarea></td>";
//MyGridRow.RowIndex is used to determine the name of popup control for the hidepopup script
MyTable += "<td><button type=\"button\" class=\"PopUpButton\" onclick=\"$find('pce" + MyGridRow.RowIndex.ToString() + "').hidePopup();\">Close</button></td></tr></table>";
return MyTable;
}
This is the pageIndexChanging event
protected void TheGrid_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
TheGrid.PageIndex = e.NewPageIndex;
LoadFromDB();
}
The LoadFromDB method here:
private void LoadFromDB()
{
try
{
LOGDBDataContext LDC = new LOGDBDataContext(ConfigurationManager.ConnectionStrings[Constants.ConnectionStringName].ConnectionString);
string Query = #"DateTimeStamp >= #0 and DateTimeStamp <= #1";
var Tolo = LDC
.Logs
.Where(Query, this.FromCalendar.SelectedDate, this.ToCalendar.SelectedDate)
.OrderBy("DateTimeStamp desc")
.Select("new (LogID, DateTimeStamp, Organization, LogEntry, ServerHostname)");
TheGrid.DataSource = Tolo;
TheGrid.DataBind();
}
catch (Exception ex)
{
//do something here
}
}
Never Mind, found the answer.
Poor Debugging
A poor attempt at
clearing the gridview that was not
invoked by the pagechanging event
Incompetence thy name is yomismo