Dear All,
I am an absolute beginner with Infopath, and I'm seeking advice on sound strategies and the best practices for working with databases.
My database has triggers to manage audit fields (e.g. created by, created on), and PK/FK referential integrity in place. I'm seeking to utilise Infopath to the max, but I don't know when I should code and when there's a way of better doing things in Infopath without programming. I'm comfortable using system.xml.xpath, but I would like to minimize programming for ease of maintenance. BTW, I use VB as it's easier for others to maintain.
I guess I don't really understand the Infopath engine deeply enough. I especially don't understand its internals and architecture i.e. what bits of the XML schema(s) get automatically populated by Infopath, and when.
Let me throw in an additional wrinkle. I'm working on a real development problem, right now, and Version 1 of the solution needs to be a bare-bones Infopath/SQL Server solution, with a full-fat client. The database is built, and all triggers have been programmed and tested (so things like internal audit fields, date/time constructs all work, so on and so forth. There are a lot of INSTEAD OF triggers.) I will then build version 2, with Enterprise MOSS 2007 with Forms Services, and I'll be writing full-featured ASP.NET Web Services for data access.
One thing I would appreciate your comments on, is what kinds of functionailty are best served at what layer in this stack.
Anyway, here's the scenario. As I say, it's a real one, but I've tried to boil it down to simple elements without making it simplistic. Specific questions are interspersed throughout the text:
Employee
- UserName (primary key)
- DisplayName
Journal
- UserName (primary key)
- CreatedOn (primary key, part of internal audit fields, auto generated by SQL Server On Insert/Update Trigger)
- JournalComment (entered by user)
Shift
- UserName (primary key, taken from selected Employee))
- ShiftStart (primary key, entered by user)
- ShiftEnd (entered by user)
ShiftActivity
- UserName (primary key, taken from Shift)
- ShiftStart (primary key, taken from Shift)
- ShiftActivityStartTime (primary key, entered by user)
- ShiftActivityCode (entered by user, needs to be validated against another SQL Server table, ActivityCodes)
- ShiftActivityHours (entered by user)
So, those are the bones. We have a master table, Employee. There's a maintenance screen. That's quite straightforward, although here's Question 1.
Q1. What's the best way of updating an Employee versus providing the functionality to add a new record? Should I use one form with two views? Two forms?
We have two sub-structures.
- Substructure 1 is the Journal, which is simply the ability of supervisors to record comments against an Employee. It's not related to Shifts at all.
- Substructure 2 is a master/detail structure of Shifts and the various ShiftActivitys recorded on the Employee timesheet.
There are thus two associated maintenance activities: entering/updating timesheets, and entering comments/viewing all comments made to date against an Employee.
I could treat Employee as a secondary data source. I only want to retrieve one specific person's record at one time. If I did that, then I would need to do things like copy certain fields (like UserName) from the secondary to the main data source. But of course, the main data source (even for entry of a single Journal record) is a repeating group.
Q2. Do I need to use things like NodeIterator and AppendChild for single record entry? If so, how would the code look? I can get the data from my secondary source using something like nav.SelectSingleNode("/dfs:myFields/dfs:dataFields/d:Employee/@UserName", NamespaceManager).Value, but I don't think I could use .SetValue with SelectSingleNode. I think I would need to use Select to be able to set single values for a single record in the repeating group of DataFields. I'd sure appreciate some insights here, becuase my understanding is real hazy.
Q3. The Journal CreatedOn date is an internal database field, populated by the trigger. But as it is a primary key, it cannot be removed from the data source. Should I put a dummy date in there simply to get past the Infopath requirement to have it populated with something before form submission? This depends on Q2.
Q3. Should I use a second view of the Journal data entry function to display all Journal comments entered to date? Obviously, given 'design once', I cannot use a master/detail control anywhere in this solution. Repeating section with controls? In a vew? A second form? What are your recommendations on best practice?
Q4. In general terms, how does Infopath manage automatic propagation of data such as primary keys from master to detail records? This is crucial for entry of new records. It's also critical when considering browser-enabled forms, where the only way to restrict detail information is through conditional formatting (and where you really don't want to retrieve more data than is actually going to be displayed on the browser form). I sure as heck don't want to retrieve everyone's Journal comments just to display the ones relevant to the selected Employee. This one is key to understanding the whole shooting match, I think.
The timesheets are completed one per employee, one per shift. They have 1 to n activities recorded on them.
Q5 Do you recommend using a single main data source with all three tables (Employee, Shift, and ShiftActivity), or do you recommend using Employee as a secondary data source purely for data retrieval, and a Main source with Shift and ShiftActivity as the records to be created (and potentially updated)?
Q6. Do I need code, or can all this be done with rules etc.? One point I would mention is that I know that I will need code, at some point, as I want to programatically add rows as long as the total hours worked (i.e. entered) is less than ShiftEndTime minus ShiftStartTime. However, for the purposes of this question, let's say I was not being fancy. Could I get away without programming?
Q7. The update function is more than a simple update. Whilst I would be updating a specfic timesheet, the changes could involve the addition or deletion of ShiftActivity rows in the database. How best should I approach this? Use code to manually generate a diffgram? Create a diffgram in the web service? Delete the lot and re-insert the rows as new?
Q8. How should I best approach the validation of ActivityCode? There are only about 50 or 60 codes, which suggest to me that they should all be loaded into the form as 'automatically retrieve data when form is loaded' in the data connection wizard. I'm guessing that there's now some XML document structure in-menory? Is that true, and if so, how best should I utilise it.
I am seeking to achieve three things with this post:
- Regarding my immediate needs, I don't want to go down ratholes trying to program my way out of something, when with a better understanding of Infopath I could be adopting a swifter, better approach;
- More generally, I'm trying to get a much deeper insight into what works well with Infopath (and equally, what doesn't, so I would appreciate any Dont Go Here warnings), and finally;
- A solid understanding of the development strategies that you, the experts, recommend.
Thanks very much for taking the time to read this very lengthy post.
I look forward to your responses, and I'd be more than happy if any given response addressed just a single point or question.
Finally, I am sure that this thread will prove extremely useful to all who come after, looking to improve their own skills and knowledgebase. I tend to reach for an assembler coding pad and a pencil when faced with something like this, and I'm quite sure that's not the best way forward. :-)
Cheers,
Donna Kelly