dotnetjunkie / solidservices

Reference architecture application for .NET that demonstrates how to build highly maintainable web services.
MIT License
198 stars 25 forks source link

Commands depending on Other Queries to work - Lookup Tables #38

Open AnasKiron opened 1 year ago

AnasKiron commented 1 year ago

Hello Steven, I hope you are healthy, and doing well.

Some of my Commands needs to do some data to work. For example, a CreateNewFacility Command depends on querying Locations; so that, When sending CreateNewFacilityCommand for handling it contains LocationId.

I am thinking of building a commands dependency list. When the client (Web, Mobile app) logs in the system, it first call GetCommandsDependencyListQuery. Then before calling a command it sees if there any Query to send to the server.

Your assistance is highly appreciated.

dotnetjunkie commented 1 year ago

I'm afraid I don't fully understand what problem you are trying to solve. Could you elaborate a bit? Do you need some kind of queuing? Or perhaps some kind of cross-cutting concern that needs to be applied to command handlers?

AnasKiron commented 1 year ago

Thanks for your prompt reply.

If the user clicks on the "Open New Facility" menu Option, it should then query the locations (For the user to select where the new facility is based on)

After that, the user fills the data fields and selects the location from the drop down list and the client app sends OpenNewFacilityCommand containing a location Id (Primary Key in the Locations Table, and Foreign Key in the Facility Table)

This means that the OpenNewFacilityCommand depends on GetLocationsQuery.

I am thinking of building a GetCommandsDependencyListQuery that returns list like:

{
    "Commands":
    {
        "OpenNewFacilityCommand":
        {
            "DependsOn"[
                "GetLocationsQuery",
                "BQuery",
                "ZQuery"
            ]
        },

        "ZCommand":
        {
            "DependsOn"[
                "AQuery",
                "BQuery",
                "ZQuery"
            ]
        }
    }
}
dotnetjunkie commented 1 year ago

I wouldn't say the command depends on the query; it simply depends on the location id. How to proceed here, depends a bit on the technology, but say that you're creating an MVC application, what I would typically do here, is create an CreateNewFacilityModel object that would both wrap the queried information and the command object:

public class CreateNewFacilityModel
{
    public CreateNewFacilityCommand Command { get; set; }

    public Location[] Locations { get; set; }
}

The MVC controller's action method can create and return this CreateNewFacilityModel to the view, while loading it with the correct data. This would mean querying the GetLocationsQuery to fill the Locaitons property of the model, but perhaps also fill some properties of the command. For instance, say that the command's LocationId is set to a default location, you can do that all in the action method:

var locations = this.qureyProcessor.Execute(new GetLocationsQuery());
return new CreateNewFacilityModel
{
    Locations = locations,
    Command = new CreateNewFacilityCommand
    {
        LocationId = locations.First().Id,
    }
}

The view can now bind to the Locations to show the drop down list, and set its selected item to the Command.LocationId.

Later on, when the model is sent back to the server, MVC will model bind that object, after which you can grab the Command object and forward it to the right command handler.

But perhaps you're not using MVC, but rather using a controllerless approach. In that case you will likely have a desktop or Angular client communicating with the service. In that case the model could be quite similar where the client constructs a model class that wraps the queries information to show to the user and the command to fill and send back.

AnasKiron commented 1 year ago

Million thanks Steven.

I am going try implement the approaches you provided.