Intercept doInsert, doUpdate and doDelete in AX 2012 - axapta

I am currently using event handler subscriptions for database logging within AX2012 on the insert, update and delete methods, however the issue i have incountered is that these events are not being fired if the method is called via a doinsert, doupdate or dodelete, is there a way i can intercept these events?

You could instead override the aosValidateInsert, aosValidateUpdate and aosValidateDelete methods. I have included references to the official documentation, sadly it currently does not explain their intended usage.
As the names imply, the methods are called before the actual operation, which may or may not suit your needs.
Remember to return true!
Also beware that adding the methods make AX use record-by-record operations instead of using set operations for example in delete_from. Also you cannot disable that using skipDataMethods (but you can using skipAOSValidation).

doXXXX methods are used specifically to avoid running any logic associated with this XXXX action, so try to intercept them goes against the design pattern of this methods and their utilisation.
Have you tried the standard database logging which you can configure and query by X++ code? For example:
http://www.jaestevan.com/howto-consultar-el-registro-de-base-de-datos-mediante-x

Related

Can set_parameter_options be added to the trajectory class?

For the Dymos problems I work with, I have code that adds states, controls, etc. in bulk and then use the set_XXX_options() method to specify specific parameter values (e.g. opt=True). This is easy for Dymos phases, because each phase has a add_XXX() method and an associated set_XXX_options() method. However, the trajectory.add_parameter() method does an associated trajectory.set_parameter_options() method.
Is there a reason the set_parameter_options() method is not available for trajectory objects? Can it be added as a method?
This is a good point and there's no reason we can't add this method, and we should for API consistency.
In the mean time, you can access the parameter_options dictionary after add_parameter to change settings. For instance,
traj.add_parameter('foo', ...)
traj.parameter_options['foo']['opt'] = True
I'll add an issue to make this a part of the API.

Revit API: 'Hidden' methods?

While using Revit API and browsing the "RevitAPI.chm" file (and browsing examples on the internet), I have noticed that some methods exist while not being listed neither in the "RevitAPI.chm" file nor suggested when using RevitPythonShell.
I explain. Let's say for instance that I have a "Space" Object, obtained with
s = FilteredElementCollector(doc).OfClass(SpatialElement).ToElements()
If I do, let's say (assuming s[0] is a valid Space object):
s[0].Geometry
I got an 'indexer object':
<indexer# object at 0x0000000000000049>
But if I do:
s[0].get_Geometry(Options())
Then I got my GeometryElement object. The same behavior goes with get_BoundingBox, for instance.
Now, that's fine, but the only way I could know about these get_something methods is by seeing examples (either on the "RevitAPI.chm", or on forums etc.). So that's kind of strange, isn't it? In the sense that these methods aren't actually listed.
So I guess my questions would be:
Is it the normal behavior? (or should I normally just get a GeometryElement object by using s[0].Geometry, for instance?)
If yes, ... why ? :D
What are these 'indexers' ?
Thanks!
Arnaud.
PS: Using Revit 2017, tests made with RevitPythonShell and pyRevit
The methods prefixed by a lowercase get_ are automatically generated getter methods. The official Revit API provides and documents the BoundingBox property on the Element class. Rather inelegantly, this so-called property takes an argument. Therefore, the C# .NET implementation generates a property getter function for it.

In Meteor.js, what's the difference between method-based database API design and the subclass approach?

Namely, what are the advantages and disadvantages of the following approaches to building a server-side database API in Meteor?
Method-based
import Db from 'Db';
Meteor.method({"insert": (data) => {Db.insert(data)});
Subclass-based
import {Mongo} from "meteor/mongo";
class MyCollcetion extends Mongo.Collection {
insert: (data) => {super.insert(data);}
}
This problem has been solved below; there is a similar question for further reading: Meteor method vs. deny/allow rules
This is mainly a matter of ease vs control. Subclassing may be easier for simple things, and methods are more powerful.
This can also be affected by your state of mind (or affect it): CRUD vs. action-based mutation.
insert/update/remove go well with a CRUD state-of-mind, while you can associate methods with action-centric RPC mutators.
Eventually, this is a matter of personal preference, so I will try to give a short factual description and let the readers to decide based on their taste.
Subclassing
By default, Meteor automatically generates mutation methods (insert, update, remove) when a collection is instantiated.
Those methods are called behind the scenes when calling MyCollection.insert(mutator, cb) on the client side (outside client-side method code). When arriving to the server, the data are first passed through allow/deny rules and then executed.
When subclassing, you override those methods and get a 'hook' into the process.
Using methods
When defining a Meteor method you get full control of the process.
You set the parameters and the name of the method and you can perform the validation and authorization as you wish.
You can also create a method stub for client-side use, which generates optimistic UI until the results of the method server execution are received.
You can use something like a validatedMethod to get some extra validation logic and modularity to your method.
You can also prevent the creation of the default mutation methods by setting a false value for the defineMutationMethods option when instantiating the collection. You can also forbid direct mutation from the client by supplying the appropriate deny rules.
While subclassing allows you to use MyCollection.insert(...), etc. on the client, you need to call the method name with the arguments that you defined in order to mutate data.

What is the principle of ractivejs's two way binding?

I'm using ractivejs,I know angularjs's two way binding based "dirty check",but I don't know the principle of ractivejs,who knows?I want a detailed answer.
Ractive doesn't diff or check anything, it uses the declarative template to know exactly what needs to be updated.
Ractive constructs a virtualDOM based on the template. The templated portions of the virtual dom (things with {{...}} in them) register with the viewmodel using the keypaths they contain.
When a ractive.set(...) or one of the other data manipulation methods occurs, dependents are notified of the change (computations and expressions, upstream and downstream keypaths, as well as observers are also notified).
Ractive uses a runloop that batches the actual DOM changes for any set operation to occur at the end of the cycle.
In addition to API calls, Ractive offers twoway binding by default. This maps needed DOM events from form input controls to the API calls to set the data to which it is bound (via the specified keypath).
Ractive does offer the .update(keypath) and .updateModel(keypath) methods which can be used to flush changes from model to view, or view to model when it is not possible for Ractive to know about them, for example using a third-party widget library.

Insert entity in preUpdate event

I'm trying to persist a History entity whenever a Message gets updated. I have too much going on behind the scenes to post all the code here and for it to make sense, but I've basically tracked the issue down to the UnitOfWork::commit method. There, the UOW first loops through the entityInsertions, and finding nothing, continues on to the entityUpdates. There the UOW's entityInsertions gets updated, but since it's already past that loop, it doesn't pick up that it still needs to persist some entities. Is there any way to force the UOW to "restart" this process? If so, how? I'm using Doctrine 2.4.
Thanks for any help!
This might be the dirtiest solution ever, but what I ended up doing was basically the following...
Create an onFlush event subscriber
Inject the entire container into the subscriber (seeing as injecting only the entity manager will result in a circular reference error)
Loop through the UnitOfWork's scheduledEntityUpdates and scheduledEntityInserts (I wasn't interested in deletes)
Handle each scheduled update or insert which you are interested in (in my case, I marked each entity I was interested in with a LoggableInterface, just to know which entities are loggable)
Handle the relevant object with a handler chain (This was just my own algorithm, yours may not require this. This was set up to handle logging of different LoggableInterface objects in different ways)
Persist the entity (the actual history event) via the entity manager, and do the following:
$classMeta = $this->entityManager->getClassMetadata(get_class($historyEntity));
$this->entityManager->getUnitOfWork()->computeChangeSet($classMeta, $historyEntity);
Profit
Hope this helps somebody!

Resources