Get asynchronous data from wcf service - silverlight

I have a wcf which retrieves information from a database.
I also have a Silverlight client application which references that service and uses it to retrieve the data.
public void init(ref Cluster cluster)
{
_SelectedCluster = cluster;
MyEntities svc = new MyEntities(new Uri("http://localhost:49672/MyDataService.svc/"));
docs = new DataServiceCollection<EC_Documents>();
var query = from c in svc.EC_Documents
where c.clusterID == _SelectedNode.ID
orderby c.clusterID
select c;
docs.LoadCompleted += docs_LoadCompleted;
docs.LoadAsync(query);
}
private void docs_LoadCompleted(object sender, LoadCompletedEventArgs e)
{
if (e.Error == null)
{
if (docs.Continuation != null)
{
docs.LoadNextPartialSetAsync();
}
else
{
_SelectedCluster.Value = docs.Count;
}
}
}
Because the call is asynchronous, I had to make docs a member of the class and check its count at the docs_LoadCompleted method.
I also have a _SelectedCluster which is an object of type Cluster as a member in the class,which holds the current cluster object in the iteration.
I have a problem assigning the result to the currently selected node _SelectedCluster.Value member.
Because the call is asynchronous, I cannot iterate on all my clusters objects and assign the result synchronously, If I do that, the assignment is always on the last cluster in the iteration.
Any suggestions?

Re-arrange your code to benefit from closures:-
public void init(Cluster cluster)
{
MyEntities svc = new MyEntities(new Uri("http://localhost:49672/MyDataService.svc/"));
var docs = new DataServiceCollection<EC_Documents>();
var query = from c in svc.EC_Documents
where c.clusterID == _SelectedNode.ID
orderby c.clusterID
select c;
docs.LoadCompleted += (s, e) =>
{
if (e.Error == null)
{
if (docs.Continuation != null)
{
docs.LoadNextPartialSetAsync();
}
else
{
cluster.Value = docs.Count;
}
}
};
docs.LoadAsync(query);
}
Now multiple calls to init can be made each using its own instance DataServiceCollection<EC_Documents>. I'm not sure what you want to do about the _SelectedNode.ID value that looks wrong to me, you ought to be passing that value in as a parameter on the init. Of course with docs now being local you will need to decide what to with it once all the docs for a cluster ID is loaded.

Related

Unable to get the Count of a returned IEnumerable in an Asychronous method

I am completely new to this but trying to learn. I'm sure there is a simple answer but I don't know enough to Google the right problem. I'm sure this must be a common problem.
In using Visual Studio 2010, WPF , .net 4.0, on a MVVM pattern using a WCF service, I have this which works perfectly:
private void RefreshEncountertimes()
{
// consume the WCF service.
this.dataservice.GetEncounterDetailsCompleted += (s, e) =>
{
this.Encounterdetails = e.Result;
};
// call the WCF service
this.dataservice.GetEncounterDetailsAsync(Calendardate);
}
where Encounterdetails is:
private IEnumerable<EncounterDetail> encounterdetails;
public IEnumerable<EncounterDetail> Encounterdetails
{
get
{
return this.encounterdetails;
}
set
{
this.encounterdetails = value;
this.OnPropertyChanged("Encounterdetails");
}
}
However, when trying to get the count on the returned Encounterdetails like this:
// search for encounters of the calendardate
private void RefreshEncountertimes()
{
// consume the WCF service.
this.dataservice.GetEncounterDetailsCompleted += (s, e) =>
{
this.Encounterdetails = e.Result;
this.ListCount = Encounterdetails.Count(); //<---CRASHES WITH INFINITIE LOOP
};
// call the WCF service
this.dataservice.GetEncounterDetailsAsync(Calendardate);
}
where ListCount is:
private int listcount;
public int ListCount
{
get
{
return listcount;
}
set
{
this.listcount = value;
OnPropertyChanged("ListCount");
CanFindPatient = ListCount > 0;
}
}
It crashes with:
Cannot evaluate expression because the current thread is in a stack overflow state.
So how do you get the Count of a returned IEnumerable from an asynchronous procedure?
Any help would be appreciated.

how do i get imagedownloadservice to work with multilist component in codenameone?

I have created a multi list in GUI Designer. I am setting the model as below
#Override
protected boolean initListModelMultiIssueList(List cmp) {
fetchIssues(cmp);
if (issueVector != null ) {
cmp.setModel(new DefaultListModel(issueVector));
System.out.println(cmp);
}
return true;
}
void fetchIssues( List c){
//fetch issues based on the searchquery hash
//first thing is to create the query from the hash
System.out.println("Starting to fetch results");
try{
java.util.List<ServiceRequest> serviceRequests = ServiceRequest.getServiceRequests(formQuery(searchQuery),true);
//we need to now populate the issueVector
//with the data
System.out.println(serviceRequests.toString());
if (issueVector != null ) {
issueVector.clear();
} else {
issueVector = new Vector();
}
int index = 0;
for (ServiceRequest serviceRequest : serviceRequests) {
Hashtable hIssue = new Hashtable();
hIssue.put("id",serviceRequest.getHref());
//System.out.println(hIssue);
ImageDownloadService.createImageToStorage(serviceRequest.getRequestPictureURL().toString(),
c, index, "icon",
"service-icon-"+ index ,null);
//hIssue.put("icon", serviceRequest.getRequestPictureURL().toString());
//System.out.println(hIssue);
//reverse geocode the location
Double x = new Double(0.0);
x=new Double(serviceRequest.getRequestLocationLatitude());
Double y = new Double(serviceRequest.getRequestLocationLongitude());
String location=reverseGeocode(x, y);
hIssue.put("location", location);
//System.out.println(hIssue);
Service service = serviceRequest.loadService();
hIssue.put("service", serviceRequest.loadService().getName().toString());
hIssue.put("reportedOn",serviceRequest.getCreatedAt().toString());
//System.out.println("Final hIssue" + hIssue.toString());
issueVector.add(hIssue);
index=index+1;
System.out.println(issueVector);
}
}catch (Exception e){
System.out.println("Error loading search results");
System.out.println(e);
}
}
The icon in the multi list GUI design has been set to the appropriate property. ImageDownloadService does download the image files but then it does not display in the list as expected. What am I doing wrong?
Its possible that the image is downloaded before the entry is available. Although its hard to tell with the code and without a clear explanation of the symptoms.
You need to first create the model and set it to the list (ideally with a blank placeholder image so the list doesn't "jump"). Then you need to loop over the list and invoke the image download service, otherwise it might return before the data is in the list and fail! This can happen if the image is already in cache so its very likely to fail fast in that case.

updating values per row in parse.com using android platform

I have a problem with updating values per row in a cloud storage site called parse.com. I am only a newbie in using parse.com. I have read the documentation about it and have understand it. But what I want to do is a little bit different from the example there. Here's my code..
public void onClick(View arg0) {
if (arg0.getId() == R.id.button1) {
ParseQuery query = new ParseQuery("inventory");
query.findInBackground(new FindCallback() {
public void done(List<ParseObject> test, ParseException e) {
ParseObject testObject = new ParseObject("inventory");
if(e==null) {
String str="";
String str2="";
for(int x =0;x<test.size();x++){
str = test.get(x).getString("name");
str2 = test.get(x).getString("quantity");
if (!str.equals(et1.getText().toString())){
str = "";
}
if(str.equals(et1.getText().toString()))
{
testObject.put("quantity", et2.getText().toString());
testObject.saveInBackground();
x = test.size();
}
else{
tv1.setText("error" + e.getMessage());
}
}
}}
});
} }
I want to update the quantity of the product name that i have inputted. when my input is equal to the name on the cloud it will update the other column which refers to the product name that I have inputted. But as a result of my code, it creates a new row, instead of updating the existing row.. what is lacking/wrong in my code? can someone please help me? :) thanks in advance! :)
I'm figuring out the same problem. I have found this:
The answer says to update an existing object, you need to retrieve it first. The retrieve method is given in the documentation on their website.
Edit:
Done! Here is how you do it; first fetch the object and then update the values you want to through the update method.
ParseQuery query = new ParseQuery("UserName");
query.getInBackground("GKIp4pxBrF", new GetCallback() {
public void done(final ParseObject object, ParseException e) {
if (e == null) {
object.put("Name", username);
object.saveInBackground(new SaveCallback() {
public void done(ParseException e) {
object.put("Name", oldname);
}
});
}
else {
e.printStackTrace();
}
}
});
In case you don't know the object code before hand, I suggest you find the required row through a query.

How to move by code the BindingSource to a specific record

Using datagridview bound to BindingSource control bound to a LINQ to SQL class, I wonder how to position the bindingSource to a specific record, that is, when I type a Product name in a textbox, the bindingsource should move to that specific product. Here is my code:
In my form FrmFind:
NorthwindDataContext dc;
private void FrmFind_Load(object sender, EventArgs e)
{
dc = new NorthwindDataContext();
var qry = (from p in dc.Products
select p).ToList();
FindAbleBindingList<Product> list = new FindAbleBindingList<Product>(qry);
productBindingSource.DataSource = list.OrderBy(o => o.ProductName);
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
TextBox tb = sender as TextBox;
int index = productBindingSource.Find("ProductName", tb.Text);
if (index >= 0)
{
productBindingSource.Position = index;
}
}
In the program class:
public class FindAbleBindingList<T> : BindingList<T>
{
public FindAbleBindingList()
: base()
{
}
public FindAbleBindingList(List<T> list)
: base(list)
{
}
protected override int FindCore(PropertyDescriptor property, object key)
{
for (int i = 0; i < Count; i++)
{
T item = this[i];
//if (property.GetValue(item).Equals(key))
if (property.GetValue(item).ToString().StartsWith(key.ToString()))
{
return i;
}
}
return -1; // Not found
}
}
How can I implement the find method to make it work?
You can combine the BindingSource.Find() method with the Position property.
For example, if you have something like this in your TextBox changed event handler:
private void textBox1_TextChanged(object sender, EventArgs e)
{
TextBox tb = sender as TextBox;
int index = bs.Find("Product", tb.Text);
if (index >= 0)
{
bs.Position = index;
}
}
This of course will depend on a lot of things like the particular implementation of the Find method the data source for the binding source has.
In a question you asked a little while ago I gave you an implementation for Find which worked with full matches. Below is a slightly different implementation that will look at the start of the property being inspected:
protected override int FindCore(PropertyDescriptor property, object key)
{
// Simple iteration:
for (int i = 0; i < Count; i++)
{
T item = this[i];
if (property.GetValue(item).ToString().StartsWith(key.ToString()))
{
return i;
}
}
return -1; // Not found
}
Do note that the above method is case sensitive - you can change StartsWith to be case insensitive if you need.
One key thing to note about the way .Net works is that the actual type of an object is not sufficient all the time - the declared type is what consuming code knows about.
This is the reason why you get a NotSupported exception when calling the Find method, even though your BindingList implementation has a Find method - the code that receives this binding list doesn't know about the Find.
The reason for that is in these lines of code:
dc = new NorthwindDataContext();
var qry = (from p in dc.Products
select p).ToList();
FindAbleBindingList<Product> list = new FindAbleBindingList<Product>(qry);
productBindingSource.DataSource = list.OrderBy(o => o.ProductName);
When you set the data source for the binding source you include the extension method OrderBy - Checking this shows that it returns IOrderedEnumerable, an interface described here on MSDN. Note that this interface has no Find method, so even though the underlying FindableBindingList<T> supports Find the binding source doesn't know about it.
There are several solutions (the best is in my opinion to extend your FindableBindingList to also support sorting and sort the list) but the quickest for your current code is to sort earlier like so:
dc = new NorthwindDataContext();
var qry = (from p in dc.Products
select p).OrderBy(p => p.ProductName).ToList();
FindAbleBindingList<Product> list = new FindAbleBindingList<Product>(qry);
productBindingSource.DataSource = list;
In WinForms there are no entirely out of the box solutions for the things you are trying to do - they all need a little bit of custom code that you need to put together to match just your own requirements.
I took a different approach. I figured, programmatically, every record must be checked until a match is found, so I just iterated using the MoveNext method until I found a match. Unsure if the starting position would be the First record or not, so I used the MoveFirst method to ensure that is was.
There is one assumption, and that is that what you are searching for is unique in that column. In my case, I was looking to match an Identity integer.
int seekID;
this.EntityTableBindingSource.MoveFirst();
if (seekID > 0)
{
foreach (EntityTable sd in EntityTableBindingSource)
{
if (sd.ID != seekID)
{
this.t_EntityTableBindingSource.MoveNext();
}
else
{
break;
}
}
}
I didn't really care for either answer provided. Here is what I came up with for my problem:
// Create a list of items in the BindingSource and use labda to find your row:
var QuickAccessCode = customerListBindingSource.List.OfType<CustomerList>()
.ToList().Find(f => f.QuickAccessCode == txtQAC.Text);
// Then use indexOf to find the object in your bindingSource:
var pos = customerListBindingSource.IndexOf(QuickAccessCode);
if (pos < 0)
{
MessageBox.Show("Could not find " + txtQAC.Text);
}
else
{
mainFrm.customerListBindingSource.Position = pos;
}

WCF: submitting to service twice

Just getting my head around WCF, so forgive me for the inelegant coding.
The issue I'm having is I seem to be submitting data twice to my service (see screenshot), even though (I think) I'm only doing it once.
Could someone please let me know what I might be doing wrong? Or even just suggest a better way to do it if I'm doing it inefficiently.
Code follows:
public void EndOfLevel()
{
GlobalVariable.TotalQuestionsAsked = 10;
GlobalVariable.CorrectDecimal = GlobalVariable.Correct / GlobalVariable.TotalQuestionsAsked;
//Show loading screen
UploadingScreen.Visibility = Visibility.Visible;
//Submit this levels results.
Service1Client client = null;
client = new Service1Client();
//Gather the results and details
Result thislevel = new Result();
thislevel.Datetime = DateTime.Now;
thislevel.result = GlobalVariable.CorrectDecimal;
thislevel.TimesTable = GlobalVariable.NeedsHelpWith;
//submit them
try
{
client.SubmitResultAsync(thislevel);
}
catch
{
MessageBox.Show("Error uploading data");
}
finally
{
client.Close();
Results r3 = new Results();
this.NavigationService.Navigate(r3);
}
}
WCF Test Client:
Cheers,
Nick
If I may, here's a pattern for managing our asynchronous calls between our WPF applications and our WCF Services.
In this section we have a public accessor to our service client that ensures that the connection to the client is open prior to calling a service method:
public static MyServiceClient Client
{
get
{
return GetMyServiceClient();
}
}
private static MyServiceClient client;
private static MyService.MyServiceClient GetMyServiceClient()
{
VerifyClientConnection();
return client;
}
private static void VerifyClientConnection()
{
if (client == null || client.State == System.ServiceModel.CommunicationState.Closed)
{
client = new MyService.MyServiceClient();
}
}
And in this section is an example of our asynchronous call and callback pattern (this example shows the delegate and callback we're using for passing exception data to our service):
public delegate void LogExceptionCompletedEvent();
public static LogExceptionCompletedEvent LogExceptionCompleted;
public static void LogExceptionAsync(SilverlightException exception)
{
string json = JsonConvert.SerializeObject(exception);
Client.LogExceptionCompleted -= client_LogExceptionCompleted;
Client.LogExceptionCompleted += client_LogExceptionCompleted;
Client.LogExceptionAsync(json);
}
private static void client_LogExceptionCompleted(object sender, AsyncCompletedEventArgs e)
{
if (LogExceptionCompleted != null)
{
LogExceptionCompleted();
}
}
In this example, a view model could attach an event handler to the LogExceptionCompleted delegate and in turn receive the result of the callback when it returns from the service.
We basically repeat this pattern for the asynchronous WCF service calls we need to make from our application and it keeps them very organized as well as unit testable.

Resources