I have this code, which I use all over my applications to save data back to the database.
public bool SaveDemo()
{
bool success = false;
try
{
using (DataTable dt = DataAccess.ExecuteDataTable("[dbo].[udp_Customers_ups]",
DataAccess.Parameter(CustomerIdColumn, CustomerId),
DataAccess.Parameter(CodeColumn, Code),
DataAccess.Parameter(CompanyColumn, Company),
DataAccess.Parameter(IsDeletedColumn, IsDeleted),
DataAccess.Parameter(LastUpdatedColumn, LastUpdated),
DataAccess.Parameter(UpdatedByColumn, UpdatedBy)))
success = true;
}
catch
{
success = false;
}
return success;
}
The code works as is, which by that I mean it saves the data back to the database. However CodeRush complains about the dt being an Unused Declaration. And since the Using is (I think) using the dt I would think that the warning is a false positive. So I am left wondering if CodeRush is wrong or if I am missing something?
What CR is trying to say is that in:
using (DataTable dt = DataAccess.ExecuteDataTable ...
you are not using the declaration of dt; the variable remains untouched after.
The refactor button will transform this to
using ( DataAccess.ExecuteDataTable ...
i.e. it will still be a using statement but you won't have a variable to refer to it.
While you're doing that, you can do some Inline Result transformations, yielding:
try
{
using (DataAccess.ExecuteDataTable("[dbo].[udp_Customers_ups]",
DataAccess.Parameter(CustomerIdColumn, CustomerId),
DataAccess.Parameter(CodeColumn, Code),
DataAccess.Parameter(CompanyColumn, Company),
DataAccess.Parameter(IsDeletedColumn, IsDeleted),
DataAccess.Parameter(LastUpdatedColumn, LastUpdated),
DataAccess.Parameter(UpdatedByColumn, UpdatedBy)))
return true;
}
catch
{
return false;
}
I'll let others question whether wrapping calls like this in a catch block is a good idea...
Related
I am getting stale element exception when I run the code. However while debugging I do not get this exception.
Here is my piece of code. Can anybody help me ? thanks
public static bool CheckListFilterResult(IList<IWebElement> gridColumns, IList<IWebElement> gridRows, string filterColumn, List<string> filters)
{
bool checkResult = false;
{
int filterColumnIndex = GetColumnIndex(gridColumns, filterColumn);
if (gridRows.Count > 0 )
{
foreach (IWebElement row in gridRows)
{
TestManager.Doc.Step("before bool match");
bool filterMatch = filters.Contains(row.FindElements(By.TagName("td"))[filterColumnIndex].Text.Trim());
if (filterMatch)
{
checkResult = true;
}
else
{
checkResult = false;
break;
}
}
}
}
return checkResult;
}
}
From looking at your code, that line is the first line where you access something from the rows collection. My guess is that it has something to do with that. Did you pull the rows collection, then apply a filter, then call this function? If so, that's probably the problem. You need to apply the filter, then pull the rows collection, then call the function.
It could be that your IWebElement row was updated by javascript while you were running your selenium code.
As explained here: http://docs.seleniumhq.org/exceptions/stale_element_reference.jsp, Stale Element Reference Exception happens when the object on the UI may have been refreshed but you are trying to access the same object. So even if the row is visible to the user, it may have been updated/replaced by javascript, then it is a different object.
The reason why it happens only occassionaly but not always could be that when you run in debug mode, you are stopping at each line of your selenium code, but javascript code doesnt stop, so the element on the UI was already refreshed, then your selenium code gets a fresh copy of the IWebElement row.
There are several possible ways of fixing this problem.
try to catch StaleElementReferenceException, if it happens, then redo whatever you are trying to do.
you can do: wait.until(ExpectedConditions.stalenessOf(row));
Hope it helps
For simple lookups, I need to perform some SQL statements on a DB2 machine. I'm not able to use an ORM at the moment. I have a working example through this code, however I'm wondering if it can be optimized more as this would essentially create a connection on each request. And that just seems like bad programming.
Is there a way I can optimize this Get() request to leave a connection open? Nesting using statements seems dirty, as well. How should I handle the fact that Get() really wants to return an object of User no matter what; even in error? Can I put this connection in the start of the program so that I can use it over and over again? What are some of the best practices for this?
public class UsersController : ApiController
{
String constr = WebConfigurationManager.ConnectionStrings["DB2Connection"].ConnectionString;
public User Get([FromUri] User cst)
{
if (cst == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
else
{
using (OdbcConnection DB2Conn = new OdbcConnection(constr))
{
DB2Conn.Open();
using (OdbcCommand com = new OdbcCommand(
// Generic SQL Statement
"SELECT * FROM [TABLE] WHERE customerNumber = ?", DB2Conn))
{
com.Parameters.AddWithValue("#var", cst.customerNumber);
using (OdbcDataReader reader = com.ExecuteReader())
{
try
{
while (reader.Read())
{
cst.name = (string)reader["name"];
return cst;
}
}
catch
{
throw;
}
}
}
}
return cst;
}
}
}
I found a great question that doesn't really have detailed answers, I feel like similar solutions exist for both of these questions...
And that just seems like bad programming.
Why do you think that?
The underlying system should be maintaining connections in a connection pool for you. Creating a connection should be very optimized already.
From a logical perspective, what you're doing now is exactly what you want to be doing. Create the connection, use it, and dispose of it immediately. This allows other threads/processes/etc. to use it from the connection pool now that you're done with it.
This also avoids the myriad of problems which arise from manually maintaining your open connections outside of the code that uses them.
Is there a way I can optimize this Get() request to leave a connection open?
Have you measured an actual performance problem? If not, there's nothing to optimize.
And there's a very good chance that hanging on to open connections in a static context in your web application is going to have drastic performance implications.
In short... You're already doing this correctly. (Well, except for that unnecessary try/catch. You can remove that.)
Edit: If you're just looking to improve the readability of the code (which itself is a matter of personal preference), this seems readable to me:
public User Get([FromUri] User cst)
{
if (cst == null)
throw new HttpResponseException(HttpStatusCode.NotFound);
using (var DB2Conn = new OdbcConnection(constr))
using (var com = new OdbcCommand("SELECT * FROM [TABLE] WHERE customerNumber = ?", DB2Conn))
{
com.Parameters.AddWithValue("#var", cst.customerNumber);
DB2Conn.Open();
using (OdbcDataReader reader = com.ExecuteReader())
while (reader.Read())
{
cst.name = (string)reader["name"]
return cst;
}
}
return cst;
}
Note that you can further improve it by re-addressing the logic of that SQL query. Since you're fetching one value from one record then you don't need to loop over a data reader. Just fetch a single literal and return it. Note that this is free-hand and untested, but it might look something like this:
public User Get([FromUri] User cst)
{
if (cst == null)
throw new HttpResponseException(HttpStatusCode.NotFound);
using (var DB2Conn = new OdbcConnection(constr))
using (var com = new OdbcCommand("SELECT name FROM [TABLE] WHERE customerNumber = ? FETCH FIRST 1 ROWS ONLY", DB2Conn))
{
com.Parameters.AddWithValue("#var", cst.customerNumber);
DB2Conn.Open();
cst.name = (string)com.ExecuteScalar();
}
return cst;
}
#David's answer addresses your actual questions perfectly but here's some other observations that may make your code a little more pallatable to you:
remove the try/catch block - all you're doing is re-throwing the exception which is what will happen if you don't use a try/catch at all. Don't catch the exception unless you can do something about it. (I see now that #David's answer addresses that - either it was added after I read it or I missed it - my apologies for the overlap but it's worth reinforcing)
Change your query to just pull name and use ExecuteScalar instead of ExecuteReader. You are taking the name value from the first record and exiting the while loop. ExecuteScalar returns the value from the first column in the first record, so you can eliminate the while loop and the using there.
I have an issue in that I'm implementing approximately 5 validation checks in a form. Each of these is located in its own method Is_XXX_Valid(). I'm looking for a way to establish that each of the methods return true; otherwise an error message should be displayed.
This however is where the problem arises, I have a solution which works partially, in that it fails to run the subsequent methods if a previous method has returned false
Here is the current code which I am using:
private void Button_Click(object sender, EventArgs e)
{
DialogResult validation_msgbox = MessageBox.Show("Are you sure you would like to submit this form?", "Submit Form?", MessageBoxButtons.YesNo);
// Run each validaion check
if (IsAAAValid() && IsBBBValid())
{
//Continue and submit data
}
else
{
//Display the errors
DialogResult Textbox_validation = MessageBox.Show(ErrorText, "Some errors were found.", MessageBoxButtons.OK);
}
}
Using the code above as an example, if IsAAAValid() returns false, then the second method is not executed and therefore the data within is not validated, leading to an incorrect dialog box if multiple errors are found.
Thanks!
This is known as "short-circuit evaluation," which you can read about here and is a usually-desirable feature of the C# programming language. You can get around it with something like this:
bool avalid = IsAAAValid();
bool bvalid = IsBBBValid();
if (avalid && bvalid)
{
//Continue and submit data
}
This will guarantee that both methods get run.
As a side note, for clarity in your code I would recommend that you rename your validation methods to signify that they have side-effects. That is, they do more than simply returning the state of the data; they actually have the potential to modify state. This is why short-circuit evaluation causes problems in this instance.
As adv12 has answered, this is called short-circuit evaluation but there is also an alternative to the way he refactored your code.
There are two boolean and operators:
&& - short-circuit evaluation
& - full evaluation
So you can simply switch to using & to call both methods regardless:
if (IsAAAValid() & IsBBBValid())
^
|
+-- only one &, not two &&
Now, having said that, personally I would write the code as adv12 did as it makes for easier to read code, not as easy to spot the use of only the one & but I thought I would post the answer for completeness.
You could simply call every method and sets a boolean value to false if any of the methods return false. At the end you could check this boolean value and display your error message.
bool isValid = true;
if(!IsValidA()) isValid = false;
if(!IsValidB()) isValid = false;
if(!IsValidC()) isValid = false;
if(!IsValidD()) isValid = false;
if(!IsValidE()) isValid = false;
if(!isValid)
MessageBox.Show("Global validation error message");
However I prefer a better approach in which you use a List<string> to accumulate error messages and print them all at the end
List<string> errors = new List<string>();
if(!IsValidA()) errors.Add("Fail on IsValidA");
if(!IsValidB()) errors.Add("Fail on IsValidB");
if(!IsValidC()) errors.Add("Fail on IsValidC");
if(!IsValidD()) errors.Add("Fail on IsValidD");
if(!IsValidE()) errors.Add("Fail on IsValidE");
if(errors.Count > 0)
{
string message = string.Join(Environment.NewLine, errors.ToArray());
MessageBox.Show("Validation errors found:" + Environment.NewLine + message);
}
I think this is better from a user perspective because you could inform her/him of the problems found in a single message and avoid that horrible user experience that happens when you tell to your user about a single problem, the user fixes the problem only to be awarded with another error message about another problem.
I have seen many posts on handling switching between frames in Selenium but they all seem to reference the Java 'ExpectedConditions' library for the below method.
ExpectedConditions.frameToBeAvailableAndSwitchToIt
I was wondering if there is any C# implementation anywhere or if anyone has any such work around?
Cheers
There isn't a direct equivalent in the C# bindings but it's very easy to do this yourself.
Remember that Selenium is open source so let's dig out the source code. Here is the Java ExpectedConditions and here is the C# set.
So what's the Java version doing? Well, not a lot I tell you.
try {
return driver.switchTo().frame(frameLocator);
} catch (NoSuchFrameException e) {
return null;
}
All it's doing is attempting to switch to the frame you tell it to, and providing it was successful (as in, there was no exception in attempting to do that), then it's assumed it can carry on.
So, all you'll need to do is do the same thing in C#, so something like (not compiled):
public static Func<IWebDriver, bool> WaitUntilFrameLoadedAndSwitchToIt(By byToFindFrame)
{
return (driver) =>
{
try
{
return driver.SwitchTo().Frame(driver.FindElement(byToFindFrame));
}
catch (Exception)
{
return null;
}
return true;
};
}
As in, keep the same concept: try to find the frame and switch to it, any exceptions then we return null and force the caller (usually a WebDriverWait instance) to iterate through again. Returning true will tell the caller that we are happy we can move on.
All the waiting & expected conditions classes live in the OpenQA.Selenium.Support.UI namespace which lives in the WebDriver.Support.dll assembly.
These answers are old and I had the same issue. I was able to use SeleniumExtras.WaitHelpers.ExpectedConditions from nuget to achieve this easily.
//wait for 10 seconds max for the frame
WebDriverWaitwait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.FrameToBeAvailableAndSwitchToIt(By.Id("FRAMEID")));
I have just committed such a ugly code. Dropping here for the future!
protected void SwitchToFrame(int iframe = 1)
{
var driver = GetWebDriver();
driver.SwitchTo().DefaultContent();
bool done = false, timeout = false;
int counter = 0;
do
{
counter++;
try
{
driver.SwitchTo().Frame(iframe);
done = true;
}
catch (OpenQA.Selenium.NoSuchFrameException)
{
if (counter <= Constants.GLOBAL_MAX_WAIT_SEC)
{
Wait(1);
continue;
}
else timeout = true;
}
} while (!done && !timeout);
if (timeout) throw new OpenQA.Selenium.NoSuchFrameException(iframe.ToString());
}
this is what I'm currently doing:
protected void setupProject()
{
bool lbDone = false;
int liCount = 0;
while (!lbDone && liCount < pMaxRetries)
{
try
{
pProject.ProjectItems.Item("Class1.cs").Delete();
lbDone = true;
}
catch (System.Runtime.InteropServices.COMException loE)
{
liCount++;
if ((uint)loE.ErrorCode == 0x80010001)
{
// RPC_E_CALL_REJECTED - sleep half sec then try again
System.Threading.Thread.Sleep(pDelayBetweenRetry);
}
}
}
}
now I have that try catch block around most calls to the EnvDTE stuff, and it works well enough. The problem I have is when I to loop through a collection and do something to each item once.
foreach(ProjectItem pi in pProject.ProjectItems)
{
// do something to pi
}
Sometimes I get the exception in the foreach(ProjectItem pi in pProject.ProjectItems) line.
Since I don't want to start the foreach loop over if I get the RPC_E_CALL_REJECTED exception I'm not sure what I can do.
Edit to answer comment:
Yes I'm automating VS from another program and yes I usually am using VS for something else at the same time. We have an application that reads an xml file then generates around 50 VS solutions based on the xml file. This usually takes a couple of hours so I try to do other work while this is happening.
There is a solution on this MSDN page: How to: Fix 'Application is Busy' and 'Call was Rejected By Callee' Errors. It shows how to implement a COM IOleMessageFilter interface so that it will automatically retry the call.
First, Hans doesn't want to say so but the best answer to "how to do this" is "don't do this". Just use separate instances of visual studio for your automation and your other work, if at all possible.
You need to take your problem statement out somewhere you can handle the error. You can do this by using in integer index instead of foreach.
// You might also need try/catch for this!
int cProjectItems = pProject.ProjectItems.Length;
for(iProjectItem = 0; iProjectItem < cProjectItems; iProjectItem++)
{
bool bSucceeded = false;
while(!bSucceeded)
{
try{
ProjectItem pi = pProject.ProjectItems[iProjectItem];
// do something with pi
bSucceeded = true;
}catch (System.Runtime.InteropServices.COMException loE)
{
liCount++;
if ((uint)loE.ErrorCode == 0x80010001) {
// RPC_E_CALL_REJECTED - sleep half sec then try again
System.Threading.Thread.Sleep(pDelayBetweenRetry);
}
}
}
}
I didn't have much luck with the recommended way from MSDN, and it seemed rather complicated. What I have done is to wrap up the re-try logic, rather like in the original post, into a generic utility function. You call it like this:
Projects projects = Utils.call( () => (m_dteSolution.Projects) );
The 'call' function calls the function (passed in as a lambda expression) and will retry if necessary. Because it is a generic function, you can use it to call any EnvDTE properties or methods, and it will return the correct type.
Here's the code for the function:
public static T call<T>(Func<T> fn)
{
// We will try to call the function up to 100 times...
for (int i=0; i<100; ++i)
{
try
{
// We call the function passed in and return the result...
return fn();
}
catch (COMException)
{
// We've caught a COM exception, which is most likely
// a Server is Busy exception. So we sleep for a short
// while, and then try again...
Thread.Sleep(1);
}
}
throw new Exception("'call' failed to call function after 100 tries.");
}
As the original post says, foreach over EnvDTE collections can be a problem as there are implicit calls during the looping. So I use my 'call' function to get the Count proprty and then iterate using an index. It's uglier than foreach, but the 'call' function makes it not so bad, as there aren't so many try...catches around. For example:
int numProjects = Utils.call(() => (projects.Count));
for (int i = 1; i <= numProjects; ++i)
{
Project project = Utils.call(() => (projects.Item(i)));
parseProject(project);
}
I was getting the same error using C# to read/write to Excel. Oddly, it worked in debug mode but not on a deployed machine. I simply changed the Excel app to be Visible, and it works properly, albeit about twice as slow. It is annoying to have an Excel app open and close dynamically on your screen, but this seems to be the simplest work-around for Excel.
Microsoft.Office.Interop.Excel.Application oApp = new ApplicationClass();
oApp.Visible = true;
oApp.DisplayAlerts = false;