| Author |
Share Topic Topic Search Topic Options
|
BillG
DevForce MVP
Joined: 05-Dec-2007
Location: Monroe, MI
Posts: 233
|
Post Options
Quote Reply
Topic: Retrieving and Updating Next Invoice # Posted: 25-Nov-2010 at 7:22pm |
I figured it out. Thanks to Ward's Bad Golfer application.
var coop = Coroutine.Start(() => CreateNewJobHistory(ssn));
|
 |
BillG
DevForce MVP
Joined: 05-Dec-2007
Location: Monroe, MI
Posts: 233
|
Post Options
Quote Reply
Posted: 24-Nov-2010 at 5:25pm |
New problem arose I moved the coroutine caller to a repository. From the ViewModel I pass the coroutine method the ssn of the current member, but I get a compile error on the line in red, the Coroutine.Start call. How can I pass a parameter to the coroutine iterator method?
//Coroutine caller
public void CreateJobHistory(string ssn)
{
var coop = Coroutine.Start(CreateNewJobHistory(ssn));
coop.Completed += (sender, args) =>
{
if (args.CompletedSuccessfully)
{
JobHistory newJob = coop.Result as JobHistory;
}
else
{
}
};
}
|
 |
BillG
DevForce MVP
Joined: 05-Dec-2007
Location: Monroe, MI
Posts: 233
|
Post Options
Quote Reply
Posted: 24-Nov-2010 at 12:41am |
I think that I figured it out. I will play around with it and post if I can't get it to work.
|
 |
BillG
DevForce MVP
Joined: 05-Dec-2007
Location: Monroe, MI
Posts: 233
|
Post Options
Quote Reply
Posted: 23-Nov-2010 at 6:34pm |
It never reaches the breakpoint.
Here is a silly thought. I am developing on a machine running Windows 7 64 bit and running the app in OOB. I know that 64 bit IE does not support Silverlight could there be problems also with OOB and 64 bit?
|
 |
DenisK
IdeaBlade
Joined: 25-Aug-2010
Posts: 715
|
Post Options
Quote Reply
Posted: 23-Nov-2010 at 6:08pm |
Have you tried letting it run and wait until it creates the new JobHistory?
Reading your post again, it sounds like what you're describing is a normal operation.
"when it executes the executeAsynce method and I step through the code it fails to fetch a row from the LocalInfos table before it hits the first yield return and the it exits the Coroutine iterator method and returns back to the calling coroutine method."
when the first yield return is hit, execution is being stopped temporarily in the CreateJobHistory routine and will only resume when the previous ExecuteAsync is completed. You saw that it exits the Coroutine iterator method back to the calling coroutine method. This is because the coroutine itself is an async operation. So the whole operation isn't done yet. At this point, the line Manager.LocalInfos.ExecuteAsync() is still getting the LocalInfos and hasn't come back yet.
Try putting your breakpoint at this line and see if it reaches it.
int nextRefNo = localInfos.NextJobHistRef;
|
 |
BillG
DevForce MVP
Joined: 05-Dec-2007
Location: Monroe, MI
Posts: 233
|
Post Options
Quote Reply
Posted: 23-Nov-2010 at 5:19pm |
same thing with another table that at least 50 rows in it. It's almost like it hasn't had time to retrieve the rows by the time it reaches the yield return statement. Does it make a difference that I am using the development server and am not using the BOS in my development machine?
|
 |
DenisK
IdeaBlade
Joined: 25-Aug-2010
Posts: 715
|
Post Options
Quote Reply
Posted: 23-Nov-2010 at 5:07pm |
Hmm, that's strange. This is a straightforward query. Could you try another query with a different entity?
|
 |
BillG
DevForce MVP
Joined: 05-Dec-2007
Location: Monroe, MI
Posts: 233
|
Post Options
Quote Reply
Posted: 23-Nov-2010 at 4:49pm |
private void CreateNewJobHistoryCoRoutine()
{
var coop = Coroutine.Start(CreateJobHistory);
coop.Completed += (sender, args) =>
{
if (args.CompletedSuccessfully)
{
newJob = coop.Result as JobHistory;
// Order newOrder = coop.Result as Order;
//// Output += newOrder.ShipName + Environment.NewLine;
}
else
{
//Error handler here
// Output += "New Order creation failed: " + Environment.NewLine;
}
};
}
//Coroutine Iterator
private IEnumerable<INotifyCompleted> CreateJobHistory()
{
var localInfoOp = Mgr.LocalInfos.ExecuteAsync() //fails to yield any rows, table has 1 row in it.
yield return localInfoOp;
//Get first LocalInfo.NextJobHistRef and increment by 1
LocalInfo localInfos = localInfoOp.Results.First<LocalInfo>();
int nextRefNo = localInfos.NextJobHistRef;
localInfos.NextJobHistRef = nextRefNo + 1;
//Create a new JobHistory
JobHistory newJob = JobHistory.Create(Mgr, CurrentMember.SocSecNo, nextRefNo);
//Create changedEntities and add first LocalInfo to it.
List<Entity> changedEntities = new List<Entity>();
changedEntities.Add(localInfos);
//Save Async
var saveOp = Mgr.SaveChangesAsync(changedEntities);
saveOp.Completed += (sender, args) =>
{
if (args.CompletedSuccessfully)
{
// var savedOrder = args.Entities[0] as Order;
// Output += "Save is successful: " + savedOrder.ShipName + Environment.NewLine;
}
else
{
//Output += "Save failed" + Environment.NewLine;
}
};
yield return Coroutine.Return(newJob);
}
|
 |
DenisK
IdeaBlade
Joined: 25-Aug-2010
Posts: 715
|
Post Options
Quote Reply
Posted: 23-Nov-2010 at 4:44pm |
|
Could you paste your code here and highlight where it fails?
|
 |
BillG
DevForce MVP
Joined: 05-Dec-2007
Location: Monroe, MI
Posts: 233
|
Post Options
Quote Reply
Posted: 23-Nov-2010 at 4:33pm |
I fixed up the new code that you gave me and it compiles fine but the problem is that when it executes the executeAsynce method and I step through the code it fails to fetch a row from the LocalInfos table before it hits the first yield return and the it exits the Coroutine iterator method and returns back to the calling coroutine method.
|
 |
DenisK
IdeaBlade
Joined: 25-Aug-2010
Posts: 715
|
Post Options
Quote Reply
Posted: 23-Nov-2010 at 4:10pm |
BillG,
I actually just wrote and tested that code snippet.
In case you haven't heard, we are creating a new section in our Wiki called the Cookbook. The Cookbook contains short code snippet to teach users how to use DF. Please see below for more info.
|
 |
BillG
DevForce MVP
Joined: 05-Dec-2007
Location: Monroe, MI
Posts: 233
|
Post Options
Quote Reply
Posted: 23-Nov-2010 at 4:03pm |
Where did you get this code snippet? Is it available with the download. If there a place to find all code snippets?
|
 |
DenisK
IdeaBlade
Joined: 25-Aug-2010
Posts: 715
|
Post Options
Quote Reply
Posted: 23-Nov-2010 at 3:21pm |
smi-mark,
Yes, that sounds like that would work as well.
|
 |
smi-mark
DevForce MVP
Joined: 24-Feb-2009
Location: Dallas, Texas
Posts: 343
|
Post Options
Quote Reply
Posted: 23-Nov-2010 at 3:06pm |
|
I haven't really looked at the other solutions, but couldn't you do something like this:
Create Invoice object Pass new invoice object to a function that makes the async retrieval code, updates the object, and then calls the update code?
This way you create and return your invoice object immediately, and the invoice Id is assigned when the async call returns
|
 |
DenisK
IdeaBlade
Joined: 25-Aug-2010
Posts: 715
|
Post Options
Quote Reply
Posted: 23-Nov-2010 at 12:39pm |
Oops, my apologies Bill. Here's a new code snippet using the NorthwindIB database. It has a similar concept to what you're trying to do.
//Coroutine caller private void BatchingMultipleAsynchronousTasksWithCoroutines() { var coop = Coroutine.Start(CreateAnOrderUsingAnotherOrder); coop.Completed += (sender, args) => { if (args.CompletedSuccessfully) { Order newOrder = coop.Result as Order; Output += newOrder.ShipName + Environment.NewLine; } else { //Error handler here Output += "New Order creation failed: " + Environment.NewLine; } }; }
//Coroutine Iterator private IEnumerable<INotifyCompleted> CreateAnOrderUsingAnotherOrder() { //Query for all Orders and suspend return calls var orderOp = _mainMgr.Orders.ExecuteAsync(); yield return orderOp;
//Get first Order property, modify it and create a new order using this modified property List<Order> orders = new List<Order>(orderOp.Results); string newShipName = orders[0].ShipName + "xxx"; orders[0].ShipName = "Vins et alcools Chevalier" + DateTime.Now.Millisecond.ToString();
//Create a new Order Order newOrder = new Order(); newOrder.ShipName = newShipName;
//Create changedEntities and add first Order to it List<Entity> changedEntities = new List<Entity>(); changedEntities.Add(orders[0]);
//Save async var saveOp = _mainMgr.SaveChangesAsync(changedEntities); saveOp.Completed += (sender, args) => { if (args.CompletedSuccessfully) { var savedOrder = args.Entities[0] as Order; Output += "Save is successful: " + savedOrder.ShipName + Environment.NewLine; } else { Output += "Save failed" + Environment.NewLine; } };
//Finally return the newly created Order yield return Coroutine.Return(newOrder); }
|
 |
BillG
DevForce MVP
Joined: 05-Dec-2007
Location: Monroe, MI
Posts: 233
|
Post Options
Quote Reply
Posted: 22-Nov-2010 at 7:46pm |
I put in the new code but I can't compile it because of the following errors:
private JobHistory GetNewJobHistory() {
var coop = Coroutine.Start(CreateJobHistory);
coop.Completed += (sender, args) =>{
if (args.CompletedSuccessfully){
return coop.Result as JobHistory;
Error 1 Cannot convert lambda expression to delegate type 'System.EventHandler<IdeaBlade.EntityModel.CoroutineCompletedEventArgs>' because some of the return types in the block are not implicitly convertible to the delegate return type C:\Software Development\VS2010\LaborWare2011\LaborWare2011\ViewModels\MemberViewModel.cs 566 21 LaborWare2011
Error 2 Since 'System.EventHandler<IdeaBlade.EntityModel.CoroutineCompletedEventArgs>' returns void, a return keyword must not be followed by an object expression C:\Software Development\VS2010\LaborWare2011\LaborWare2011\ViewModels\MemberViewModel.cs 566 21 LaborWare2011
}
else
{
//Error handler here
}
};
}
|
 |