-
Hello All, using Csla.Core;
using Csla.Rules;
using Csla;
namespace Pcdl.Biz.BusinessRules
{
public class TestBusinessRule : BusinessRuleAsync
{
//Note the rule will not run if any of the input properties are empty or null
//Make sure all methods are Async if you are using async methods. It will not work if you are using sync methods
public TestBusinessRule(
IPropertyInfo tParcelOldMBProperty,
IPropertyInfo tParcelOldPGProperty,
IPropertyInfo tParcelOldPCLProperty)
: base(tParcelOldMBProperty)
{
//Note Order make a difference with InputProperties
//PrimaryProperty = tParcelOldMBProperty;
InputProperties.Add(tParcelOldMBProperty);
InputProperties.Add(tParcelOldPGProperty);
InputProperties.Add(tParcelOldPCLProperty);
}
protected override async Task ExecuteAsync(IRuleContext context)
{
string OldMBValue = (string)context.InputPropertyValues[InputProperties[0]];
string OldPGValue = (string)context.InputPropertyValues[InputProperties[1]];
string OldPCLValue = (string)context.InputPropertyValues[InputProperties[2]];
if (!string.IsNullOrEmpty(OldMBValue) && !string.IsNullOrEmpty(OldPGValue) && !string.IsNullOrEmpty(OldPCLValue))
{
IDataPortal<ParcelNewList> dpPNLCommand = context.ApplicationContext.GetRequiredService<IDataPortal<ParcelNewList>>();
//This failed I figured maybe the Async method was not set up correctly. Lets make it simple.
//ParcelNewList objPNList = await dpPNLCommand.FetchAsync(OldMBValue, OldPGValue, OldPCLValue);
ParcelNewList objPNList2 = null;
//This fails. Everthing else is skipped and hangs. Set business object to IsBusy = true
//objPNList2 = await dpPNLCommand.CreateAsync();
//Created GetParcelNewListTask method to see if I can get the Task to work.
//This worked and returned the Task
var objPNList = GetParcelNewListTask(dpPNLCommand, OldMBValue, OldPGValue, OldPCLValue);
string test = "did it work";
try
{
//This fails. When I try to get the results from the task. Everthing else is skipped and hangs. Sets business object to IsBusy = true
objPNList2 = objPNList.Result;
}
catch (Exception ex)
{
//No error is thrown. This is skiped and exit out
string test1 = ex.Message;
}
string test2 = "did it work";
if (OldMBValue != "0000" && OldPGValue != "0000" && OldPCLValue != "0000")
{
foreach (ParcelNewInfo objPN in objPNList2)
{
//Do something here with the list
}
}
}
}
private Task<ParcelNewList> GetParcelNewListTask(IDataPortal<ParcelNewList> UOW, string MBSearch, string PGSearch, string PCLSearch)
{
//This works and returns the Task
var objPNList = Task.FromResult(UOW.CreateAsync());
return objPNList.Result;
}
}
} |
Beta Was this translation helpful? Give feedback.
Replies: 13 comments 8 replies
-
I noticed that my pages did not have a the latest. So Im updating everything now. CSLA to 8.2.5 and .NetCore to 8.0.7 |
Beta Was this translation helpful? Give feedback.
-
FYI - I updated all the Libraries to latest CSLA to 8.2.5 and .NetCore to 8.0.7 and I get the same results. |
Beta Was this translation helpful? Give feedback.
-
I have had no luck performing an external call like you've done in my business object async. Particularly when using a factory class. I get the same results—a hang or immediate return with no call performed.
What I ended up doing was removing the Async from the name of the inherited class call and then doing this in a non-async method:
obj = Task.Run(async () => await portal.FetchAsync(criteria)
.ConfigureAwait(false))
.GetAwaiter()
.GetResult();
I have never gotten async rules to work when calling a factory class to get data.
Have a nice day.
Kevin
…________________________________
From: jhuerta3 ***@***.***>
Sent: Thursday, July 11, 2024 12:56 PM
To: MarimerLLC/csla ***@***.***>
Cc: Subscribed ***@***.***>
Subject: Re: [MarimerLLC/csla] Update from 7.0 to 8.2.4 SaveAsync fails due to object being IsBusy = true after Rule is hit with Fetch command/UOW (Discussion #4096)
FYI - I updated all the Libraries to latest CSLA to 8.2.5 and .NetCore to 8.0.7 and I get the same results.
—
Reply to this email directly, view it on GitHub<#4096 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AGJTVDR3YPILJ3AL3D7L57DZL3INRAVCNFSM6AAAAABKXNIXPGVHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTAMBSGQ2DGNI>.
You are receiving this because you are subscribed to this thread.Message ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
There are some capabilities in CSLA 8 to help make async rules easier to work with. One thing is This is particularly useful in, for example, a fetch operation method where you want to run the rules after loading the data: [Fetch]
private async Task FetchAsync(...)
{
// load the data into the object
await BusinessRules.CheckRulesAsync();
} That'll ensure the async rules are finished before the object graph is returned to the client. On the client side, the same thing is true. If your code calls Finally, on the client side, if you aren't manually saying to check rules, but allowing the rules engine to "do its thing" - the most common scenario in my experience, there are some things you can do. First, Second, you can use the private async Task SaveButtonClicked()
{
await obj.WaitForIdle();
await obj.SaveAndMergeAsync();
} The |
Beta Was this translation helpful? Give feedback.
-
The business rule looks partially okay to me. I would assume the |
Beta Was this translation helpful? Give feedback.
-
When I do this:
```csharp
private async Task GetBidHolidayInformationAsync(IRuleContext context)
{
var portal1 = context.ApplicationContext.GetRequiredService<IDataPortal<ConstructionBidPlannedHolidayInfoList>>();
BidStartDateEndDateCriteria criteria = new BidStartDateEndDateCriteria(bidKey, beginDate, endDate);
var obj1 = await portal1.FetchAsync(criteria);
totalHolidayCount = (short)obj1.Count();
}
```
It invokes this:
```csharp
[Serializable]
[Csla.Server.ObjectFactory(typeof(ConstructionBidPlannedHolidayFactory), "GetAllReadOnlyAsync")]
public class ConstructionBidPlannedHolidayInfoList : ReadOnlyListBase<ConstructionBidPlannedHolidayInfoList, ConstructionBidPlannedHolidayInfo>
{
public ConstructionBidPlannedHolidayInfoList()
{
AllowNew = true;
AllowRemove = true;
AllowEdit = true;
IsReadOnly = false;
}
}
}
```
Which calls this:
```csharp
public async Task<object> GetAllReadOnlyAsync(int bidId)
{
var task1 = await _repository.GetAllAsync(bidId);
var listing = _context.CreateInstanceDI<ConstructionBidPlannedHolidayInfoList>();
SetIsReadOnly(listing, false);
foreach (var item in task1)
{
var obj = _mapContainer.Map<ConstructionBidPlannedHoliday, ConstructionBidPlannedHolidayInfo>(item);
obj.HolidayName = await GetHolidayAsync(obj.CompanyHolidayKey);
MarkOld(obj);
MarkAsChild(obj);
listing.Add(obj);
}
SetIsReadOnly(listing, true);
return listing;
}
```
One of several things will happen:
1. var obj1 = await portal1.FetchAsync(criteria); IMMEDIATE RETURN—No invocation of factory classes
2. Return is null
3. the fetch never returns and the cpu hovers around 2%
…________________________________
From: Stefan Ossendorf ***@***.***>
Sent: Friday, July 12, 2024 3:37 PM
To: MarimerLLC/csla ***@***.***>
Cc: Kevin Joseph Cabral ***@***.***>; Mention ***@***.***>
Subject: Re: [MarimerLLC/csla] Update from 7.0 to 8.2.4 SaveAsync fails due to object being IsBusy = true after Rule is hit with Fetch command/UOW (Discussion #4096)
The business rule looks partially okay to me. I would assume the dpPNLCommand is an actual command and should have an ExecuteAsync() and not FetchAsync().
Where are the rules exeucted? Client or server? It's easy to deadlock your client (e.g. WPF/WinForms) when using .Result. So that must be avoided at all costs.
—
Reply to this email directly, view it on GitHub<#4096 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AGJTVDVWMGXJQRVN3YWDDHLZMBECPAVCNFSM6AAAAABKXNIXPGVHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTAMBTGU4DSOI>.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
I'm guessing your If you have async rules, you need to wait for them to complete before exiting the method. You could call |
Beta Was this translation helpful? Give feedback.
-
But that class is a businessReadOnly, so there shouldn't be invocation of the rules. Is that perspective correct?
Have a nice day.
Kevin
…________________________________
From: Rockford Lhotka ***@***.***>
Sent: Sunday, July 14, 2024 12:32 PM
To: MarimerLLC/csla ***@***.***>
Cc: Kevin Joseph Cabral ***@***.***>; Mention ***@***.***>
Subject: Re: [MarimerLLC/csla] Update from 7.0 to 8.2.4 SaveAsync fails due to object being IsBusy = true after Rule is hit with Fetch command/UOW (Discussion #4096)
I'm guessing your GetAllReadOnlyAsync method isn't bypassing the rules as the child objects are loaded, so as the properties are set all the rules are being invoked - sync and async. That may be what you want.
If you have async rules, you need to wait for them to complete before exiting the method. BusinessBase has a WaitForIdle method that you can await so you know when the rules are done.
You could call WaitForIdle in each iteration of the foreach loop. Or you can get its Task and add it to a list of tasks, then wait for all those tasks after exiting the foreach loop.
—
Reply to this email directly, view it on GitHub<#4096 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AGJTVDSKSFHUGKZHHDW4TZTZMK725AVCNFSM6AAAAABKXNIXPGVHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTAMBUGQ4TQNI>.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
Hello @rockfordlhotka, I made suggested changes but Im still having issues with the Insert process. I have two issues. The First is I am not able to retrieve the key value after the data is saved into the database. The second is my application hanges after the Business object Insert method ends. Can you verify my code and see if its correct. The good thing is I dont get IsBusy = true any more after I added WaitForIdle `
` |
Beta Was this translation helpful? Give feedback.
-
Hello @rockfordlhotka ,
|
Beta Was this translation helpful? Give feedback.
-
Hello @rockfordlhotka , The following below works fine. I am able to save to the database and the code continues to process in the UI but I had to remove all the Async calls and syntax. Maybe something is wrong with my syntax. `
` |
Beta Was this translation helpful? Give feedback.
-
Hello @rockfordlhotka and @kcabral817 , I finally got my code working. This is what I had to do to get it to work and what I found.
Below is my code. I will research more moving forward. If someone can use these notes good. Thank you for you help. `
}
` Thank you. |
Beta Was this translation helpful? Give feedback.
-
I forgot to add that I also added await BusinessRules.CheckRulesAsync(); to all my Async Fetch methods. |
Beta Was this translation helpful? Give feedback.
Hello @rockfordlhotka and @kcabral817 ,
I finally got my code working. This is what I had to do to get it to work and what I found.
1.1 - What I notice is that once the first property is loaded with data that kicks off a business rule the object.IsBusy = true.
1.2 – After loading all the data then call object.WaitForIdle() to set the object.IsBusy = false;
The next thing is I had to set the insert methos and save methods to Sync and not Async.
2.1 – If I didn’t do this it wo…