Need advice on Entity Manager - winforms

I open up a Member form for Add/Editing members. It has its own entity manager and when the Save button is clicked I close the form and go back to a list form.
When the save is processed, I call a routine called CalculateOwing which calculates the members balance. This method is in a separate .cs file cause it can be called from many areas in the application.
Should the CalculateOwing method be in a separate entity manager or in the same entity manager as the member record being processed?

A response to this question can be seen at http://www.ideablade.com/forum/forum_posts.asp?TID=4686&title=need-advice-on-entity-manager
EDIT:
Including the response here.
"If you want the results of CalculateOwing to be part of the same database transaction, you need to call it before the Save completes and on the same EntityManager that the Save is using."

Related

Lock a record from other users when editing by single user in CakePHP 2.4

I am implementing a CakePHP 2.4 app.
I have User and Article as Models.
I have no articles/view action; only articles/edit and articles/delete actions.
When any User accesses the articles/edit webpage regardless as a GET or POST, that particular Article is locked from editing/deleting by other Users.
The following is the crucial part I need advice on.
If a User stays on articles/edit/23 but there is no activity for 30 minutes,
-- OR --
When the User leaves articles/edit/23 page,
then the articles/23 is now available for edit/delete by other Users.
Off the top of my mind, i know that in articles table, i need a field called currently_locked_by field that holds the user_id of the User currently in control.
My problem is with detecting the session inactivity and knowing that the User has left the edit page.
I am defining session inactivity in the edit page as when the User does not type anything in any input elements or changes any dropdown selection or checks/uncheck any checkbox.
Suggestions?
You could create a lock table with a combination of the user, resource and lock time. (Regarding your spec's when to start the inactivity - I recommend going simpler to start: "when they person loads the page". Otherwise you are also writing javascript to write to your database at the end of every field change.)
Whenever a person goes to the edit page,
They check that table for the resource and lock time. If the record does not exist or the lock time has been exceeded it is safe for them to edit.
If they can edit, then they insert a record as needed (and delete any records with that resource.)
This should take care of the timeout requirement as long you make sure the person still has a lock (or another hasn't locked the record) when they try to save their changes.
One technique to handle the leaving of pages, is to put in a beforeFilter test that removes all locks for that person. The downsides
You still can't tell if the person leaves and goes to some external
site.
The beforeFilter does add overhead to every page view.
If your users run two or more tabs, then navigating other tabs will
release the lock.
You could also just have every outbound link on that page release the lock (like going to an interstitial page) and let any departures via closing the tab, using address bar, etc timeout. (It depends on how your users work.)

Salesforce Trigger workflow on record delete

I want to listen change in my legacy system whenever there is any change in SF object (add/update/delete). So I have created outbound message and workflow. But in workflow I don't see any way to fire if object is deleted.
Is there anyway I can trigger outbound message on record delete? I know have heard that it can be done by trigger. But I don't want to write apex code for this.
To the best of my knowledge it cannot be done, the workflow actions are decoupled from the workflow rule (you can even reuse them) so they probably do not receive the transaction scope and when they execute the record is already gone and any reference inside action would point to a non-existing data. Thus the only way I know how to do it is via trigger.
Here is a workaround. However this will only be able to capture deletion made via std. Salesforce UI.
1.Create a custom checkbox field "Is Deleted"
2.Override the Del link with a custom VF page, that first updates the record status to "Is Deleted", and deletes the record.
3.Write workflow rule using the "Is Deleted" field.
Perhaps a compromise architecture would be to write an extremely small and simple after delete trigger that simply copies the deleted records in question to some new custom object. That new custom object fires your workflow rule and thus sends the outbound message you're looking for. The only issue with this would be to periodically clean up your custom object data that would grow in size as you deleted records from your other object. In other words, your "scratch" object would just need periodic cleaning - which could be done on a nightly schedule with batch Apex.
Here's a delete trigger that would do the trick using Opportunity as an example:
trigger AfterDelete on Opportunity (after delete)
{
List<CustObj__c> co = new List<CustObj__c>();
for(Opportunity o : Trigger.old)
{
CustObj__c c = new CustObj__c();
c.Name = o.Name;
c.Amount__c = o.Amount;
c.CloseDate__c = o.CloseDate;
c.Description__c = o.Description;
// etc.
co.add(c);
}
insert co;
}
It's not ideal but at least this would save you from having to code your own trigger-based outbound messages. These can only be done using the #Future annotation, btw, since callouts directly from triggers are forbidden. Hope that helps.
write a single email send in the trigger delete event. You have it in less than 1 hour.

CakePHP afterSave Timing

I have a situation where, in a model's afterSave callback, I'm trying to access data from a distant association (it's a legacy data model with a very wonky association linkage). What I'm finding is that within the callback I can execute a find call on the model, but if I exit right then, the record is never inserted into the database. The lack of a record means that I can't execute a find on the related model using data that was just inserted into the current.
I haven't found any mention of when data is actually committed with respect to when the afterSave callback is engaged. I'm working with legacy code, but I see no indication that we're specifically engaging transactions, so I'm trying to figure out what my options might be.
Thanks.
UPDATE
The gist of the scenario is this: We're taking event registrations, but folks can be wait listed. A user can register (or be registered) for a given Date. After a registration is complete, I need to check the wait list for the existence of a record for the registering user (WaitList.user_id) on the date being registered for (WaitList.date_id). If such a record exists, it can be deleted because it's become an active registration.
The legacy schema puts me in a place where the registration isn't directly tied to a date so I can't get the Date.id easily. Instead, Registration->Registrant->Ticket->Date. Unintuitive, I know, but it is what it is for now. Even better (sarcasm included), we have a view named attendees that rolls all of this info up and from which I would be able to use the newly created Registration->id to return Attendee.date_id. Since the record doesn't exist, it's not available in the view.
Hopefully that provides a little more context.
What's the purpose of the find query inside of your afterSave?
Update
Is it at all possible to properly associate the records? Or are we talking about way too much refactoring for it to be worth it? You could move the check to the controller if it's not possible to modify the associations between the records.
Something like (in psuedo code)
if (save->isSuccessful) {
if (onWaitList) {
// delete record
}
}
It's not best practice, but it will get you around your issue.

Is DataWriter the right solution for ExtJS CRUD?

I am asking this because in ExtJS in Action book, Page 442, the author said:
"at the time of this writing,
DataWriterhas some undesirable
behaviors such as creating a Record
for a Store even if the create action
failed in the backend"
Is this still the case with ExtJS 3.3.1? If not, should DataWriter be used instead of our own CRUD code?
That is an interesting quote. The actions happen in sort of the reverse order.
When a new record is created in the store (a phantom record) and the save method is called on the store, the DataWriter will send information for any phantom records to the create action so that they may be created on the back end.
If the response from the server dictates that there was a failure and the correct record data is not sent back, I do not believe the record will remain in the store.
I believe the DataWriter can be valuable to performing CRUD operations on a store.

Retrieving common data on different forms

Lets take an example of WinForms applcation and making invoice. On the Invoice form we retrieve a list of products, so the user will be ale to pick products for current invoice. Lets also consider that during this process user realizes that he needs to add a new product (or edit current) to ProductList before he can place it in invoice. So he opens a ProductForm where all the products are retreived (again).
It could also be in opposite order, that user first edits Products, and then without closing the Products Form, opens new Invoice. The principle is that data is two times loaded, and effectively its the same data.
What is the propper way to handle this scenario, so we can tell one form that data is already loaded, and to retrieve that data from memory? And when all the consumers (Forms) of the data are closed, then also the data should be released from memory? Or I am going in wrong direction, and there is a better way?
Thanks,
Goran
Definitelly go with data loaded "twice" or you will introduce much worse problems.
Sharing data means sharing ObjectContext. Even in WinForms application this is considered as bad approach. Check this article (it is about NHibernate but the description is valid for EF as well).
The problem is that ObjectContext is unit of work. If share context between two windows you can easily get into situation where you modify data in first window (without saving them!) and you continue in second window where you push save button but it will save data from both windows! You can't selectively save data only from one window when you share the context.
If the Controls that are using the data are all child controls of a shared Parent control, then you could just pass around the datacontext, so that they all shared the same datacontext.
However, the general use case with databases, which is what backs EF in most cases, is to read the data in each time that it is needed.
A solution to this if as you say you already have the item being used in one form is to just take a Refrence to that item into your new form.
So in the case Where you have an invoice which has a Product List and you want to add to the product list, you could pass the product list from the invoice to the opening product list.
There are some issues with this:
If another user changes the datasource while one has opened it (a.k.a. Concurrency)
Handling save don't save scenarios where they may have made a change in one area that they don't actually want added to the data.
However, unless it is a true performance issues, I would just load the data every time. You can simplify this a lot by using the repository pattern, so you can just call a single method to get a list of products or an invoice, or whatever part of data you need.

Resources