I have come across a very frustrating and perplexing problem. I have been all over google and have been unable to find anything about it.
System specs:
I am running an Access .mdb front end with a SQL Server back end. The tables all have primary keys declared and foreign key relationships. The SQL Server tables are linked to the Access front end via ODBC. A single copy of the Access front end file is located in a shared network location and is accessed by multiple users at any given time. There are about 15 to 20 users that could have an instance of the Access front end file open on their machine. In the front end file there are a lot of queries, forms, and reports. All of the forms and reports have some amount of vba that go along with them. The SQL Server is the Express edition of 2008 R2. All of the user are running Office 2007.
Problem:
I spent a great deal of time updating data in our system about two years ago. Over the last couple of months users have been telling me that data is missing or incorrect when I know that it should be correct after my updates. Because I create backups for the SQL Server database periodically, I was able to look at older version of the database and discovered that the data had in fact been updated as I thought, but now those line of data are missing or incorrect. I am the only person who knows how to update data en masse, and no one would go in and intentionally alter this data. It is widespread enough, that I know it is not the result of an accidental keystroke.
The front end does have some built in features that are used for copying data which I did not create. (In fact I inherited this whole system, and have just made additions and modifications here and there) We are a manufacturing firm that creates custom versions of our standard products, so bills of materials often need to be copied, then modified for the custom version. Yesterday I executed such as copy and ended up with a crazy result. When I copied the bill of materials from the original, it copied an old version of the original product's bill of materials into the custom version's bill. It was insane. I double checked the bom of the original and it was the up to date version, but somehow the old version of the bom ended up copying into the custom product's bom. The only thing I can think of, is that somehow the old data has managed to store itself (from as long as two years ago) in the Access front end, and somehow that data was pulled from by the vba that executes the bom copy function.
Has anyone seen something like this before?
Just a suggestion; use a distributed front end method. It's an industry standard, as it's a known fact that a shared front end can lead to corruption. Each user should have a copy of the front end on their local HD, and it's easy enough to distribute using a simple BAT file to copy the front end from the network to the HD.
Aside from that, data doesn't magically revert to ancient records. It's pulling that data from somewhere. You will need to track the data path and see where it originated from. Look at the code behind the "Copy" button. If it's pulling from a linked table, open that table in SQL Server and run the SQL that the Copy function is executing and see if the resulting data is identical to what Access thinks it is. If not, write a SQL string to filter the data based on what Access returned and see if that record still exists in the table. If it does, look at each field and see if you can determine why it's pulling the old record instead of the new record. It's pulling this data from somewhere, you have to determine where that "somewhere" is.
Related
When working with an Access .accdb, every time I open the file, I see that the 'date modified' in the filesystem changes to now. This makes me nervous. I want it to stop.
I can't be the only person who has ever saved a working db, and opened it a few weeks or months later to an error. Sure, I probably have backups, and backups to my backups, and table data saved separately from my code, and version history taking up multiple gigabytes of the filesystem or in emails or where ever... but it still makes my heart jump a little whenever I see the date modified update on open, when I haven't touched the DB in some time.
Have I flipped a switch somewhere that makes it do this? Is this expected behavior? How can I stop it?
To replicate this, create a new accdb, save and close. Put something in it, nothing, or close it only a second after creating it. Open an windows explorer for the directory the accdb is saved in, and note the date modified value. Open the file at least a minute after the displayed date modified file. alt-tab back to the explorer window, and you see the date modified has changed.
That's the default behaviour, even with a native Access MDB file. They don't work like a normal file that you have to explicitly modify to update the date - it does some things when you open it up, whether you want it to or not.
Just did a quick test - if you set the database file to read-only, it doesn't update itself.
I construct my MS Access Applications into front end and a back end. The Front end database is made up of all the the application objects like the Queries, Forms, Reports, and Modules. The back end database is made up of the tables and links to other data sources.
Many people consider this a Microsoft Access Generally Accepted Best Practice.
So much so that Microsoft includes a Wizard to do the split for you. Shown here
10 Reasons to Split an Access Database
Once the database has been split, It makes is a whole lot more manageable. The Front End can be marked read-only. The Back End remains writable.
i have 2 questions when i use access:
i create a form with comboBox and calenders, i want to choose an employee
from combobox and from date and to date and when i click ok i will send these
parameters to a query to return the result in a query (result is the calculation
of it's salary).
i know how to release an access project to be useful to user that can't
access tables and queries only forms.
is there any way to change the access project from release mode to development
one, because supposed that an error occurred, how to solve it without loosing
my data.
Note: i don't have client/server i develop a program and i release it and
give this release to the user, after a specific time this user tell me that
an error occurred, and he need data inserted from this program to database.
i can solve this problems and release another version of program, but the
main problem is how to take all data from the old program to the new one.
-- You can reference form control in a query:
SELECT FROM MyTable
WHERE EmployeeID = Forms!MyForm!cboEmployee
AND SomeDate BETWEEN Forms!MyForm!txtDateStart And Forms!MyForm!txtDateEnd
You could also build an SQL string and use it as the record source for a form or in VBA.
-- Access should be split into front-end (forms, reports, etc) and back-end (data). When you make changes to the front-end, you create a new mde or accde and send that to the users. The data stays on a server in the back-end.
See: http://msdn.microsoft.com/en-us/library/aa167840(v=office.11).aspx
EDIT
From your comments, it seems that each application has a single user, if this is the case, splitting is not essential, but it can still be a good idea. The user will get two databases, one for data and one for forms etc and only the one for forms gets replaced. You will need to include a routine to locate and link the back-end tables.
However, if this is not possible, an mde or accde does not hide the data, you can send your revised copy and include a routine to import from the previous mde/accde.
EDIT 2
There are wizards that will split your database for you and link the tables. Where you find them varies slightly from version to version, but they are under the menu item Database Tools. The only problem with this is that the linked table holds the location for the back-end, which is on your computer, not on your users computer. Linked tables are how you access data in the second database. These act as if there are tables in the first database, except you cannot change them. Unfortunately, linked tables hold the location of the back-end, so this will have to be changed if you are sending it to a users. You can either write code, or show your user how to use the linked table manager. This may lead to confusion and may not be worth the effort for one PC. (See also http://www.alvechurchdata.co.uk/accsplit.htm)
Alternatively, you can split the database on your PC and make all the changes to forms etc that you want, then add some code that will import the tables and other data for the user into your new copy. The user will follow the instructions in your code to import the tables. As an aside, you will find that development is a lot safer on a split database. You should also decompile from time to time, which you can find at http://www.granite.ab.ca/access/decompile.htm.
If you want to protect your code, you can create a compiled version of this new copy, the extension for a compiled Access database is *.accde, for 2007 onward and *.mde for prior versions. This is what I thought you meant by 'i know how to release an access project'.
A while back I asked this question about splitting an MS Access application, and possibly leaving some of the non-table functionality in the BE. Well, I'm at it again... :)
Some of my tables will be such that they are never updated by the user. The data feed to these tables will be a fairly intensive code process, run daily, that extracts from Oracle, majorly massages the data & then writes to my tables (very different structure from Oracle).. There's no practical way to make it a live link to Oracle. All of the code for this will be in Modules/Class Modules, none in Forms. It absolutely would need to be changed if the schema of either the Access file or the Oracle server changes.
Given the foregoing, FE or BE?
I would put the code modules in a FE so that you can re-link a copy of the FE to a testing/development BE as the need arises. The code FE needn't be the same application FE you distribute to your users.
I don't know that I'm understanding your description -- from what I get it sounds like a temp table, i.e., with data that is replaced with something else on a regular basis. In that case, you certainly don't want it either in your front end or in your back end (if the back end is a Jet/ACE database). If that's what you have here, this data belongs in a separate back end.
For managing links to multiple back ends, you might find my Reconnect Utility useful. Since all of my apps have a temp database that's part of the front end, all of them need the ability to easy reconnect to more than one back end (the linked table manager is a real pain for that). Some of my apps have as many as four different target databases that the linked tables point at, and it's much easier to do that with my utility. It only works with Jet/ACE back ends, though (I've sketched out handling of other data sources, but never finished it, because I never needed it in any of my own applications!).
I have created an MS Access 2003 application, set up as a split front-end/back-end configuration, with a user group of about five people. The front end .mdb sits on a network file server, and it contains all the queries, forms, reports, and VBA code, plus links to all the tables in the back end .mdb and some links to ODBC data sources like an AS/400. The back end sits on the same network file server, and it just has the table data in it.
This was working well until I "went live" and my handful of users started coming up with enhancement requests, bug reports, etc. I have been rolling out new code by developing/testing in my own copy of the front-end .mdb in another network folder (which is linked to the same back-end .mdb), then posting my completed file in a "come-and-get-it" folder, alerting the users, and they go copy/paste the new front-end file to their own folders on the network. This way, each user can update their front end when they're at a 'stopping point' without having to boot everyone out at once.
I've found that when I'm developing now, sometimes Access becomes extremely slow. Like, when I am developing a form and attempt to click a drop-down on the properties box, the drop-down arrow will push in, but it will take a few seconds before the list of options appears. Or there's tons of lag in selecting & moving controls on a form. Or lots of keyboard lag.
Then, at other times, there's no lag at all.
I'm wondering if it's because I'm linked to the same back end as the other users. I did make a reasonable effort to set up the queries, forms, reports etc. with minimal record locking, if any at all, depending on the need. But I may have missed something, or perhaps there is some other performance issue I need to address.
But I'm wondering if there is an even better way for me to set up my own development back-end .mdb, so I can be testing my code on "safe" data instead of the same live data as the rest of the users. I'm afraid that it's only a matter of time before I corrupt some data, probably at the worst possible moment.
Obviously, I could just set up a separate back-end .mdb and manually reconfigure the table links in the front end every time, using the Linked Table Manager. But I'm hoping there is a more elegant solution than that.
And I'm wondering if there are any other performance issues I should be considering in this multi-user, split database configuration.
EDIT: I should have added that I'm stuck with MS Access (not MS-SQL or any other "real" back end); for more details see my comment to this post.
If all your users are sharing the front end, that's THE WRONG CONFIGURATION.
Each user should have an individual copy of the front end. Sharing a front end is guaranteed to lead to frequent corruption of the shared front end, as well as odd corruptions of forms and modules in the front end.
It's not clear to me how you could be developing in the same copy of the front end that the end users are using, since starting with A2000, that is prohibited (because of the "monolithic save model," where the entire VBA project is stored in a single BLOB field in a single record in one of the system tables).
I really don't think the problems are caused by using the production data (though it's likely not a good idea to develop against production data, as others have said). I think they are caused by poor coding practices and lack of maintainance of your front end code.
turn off COMPILE ON DEMAND in the VBE options.
make sure you require OPTION EXPLICIT.
compile your code frequently, after every few lines of code -- to make this easy, add the COMPILE button to your VBE toolbar (while I'm at it, I also add the CALL STACK button).
periodically make a backup of your front end and decompile and recompile the code. This is accomplished by launching Access with the /decompile switch, opening your front end, closing Access, opening your front end with Access (with the SHIFT key held down to bypass the startup code), then compacting the decompiled front end (with the SHIFT key held down), then compiling the whole project and compacting one last time. You should do this before any major code release.
A few other thoughts:
you don't say if it's a Windows server. Linux servers accessed over SAMBA have exhibited problems in the past (though some people swear by them and say they're vastly faster than Windows servers), and historically Novell servers have needed to have settings tweaked to enable Jet files to be reliably edited. There are also some settings (like OPLOCKS) that can be adjusted on a Windows server to make things work better.
store your Jet MDBs in shares with short paths. \Server\Data\MyProject\MyReallyLongFolderName\Access\Databases\ is going to be much slower reading data than \Server\Databases. This really makes a huge difference.
linked tables store metadata that can become outdated. There are two easy steps and one drastic one to be taken to fix it. First, compact the back end, and then compact the front end. That's the easy one. If that doesn't help, completely delete the links and recreate them from scratch.
you might also consider distributing an MDE to your end users instead of an MDB, as it cannot uncompile (which an MDB can).
see Tony Toews's Performance FAQ for other generalized performance information.
1) Relink Access tables from code
http://www.mvps.org/access/tables/tbl0009.htm
Once I'm ready to publish a new MDE to the users I relink the tables, make the MDE and copy the MDE to the server.
2) I specifically created the free Auto FE Updater utility so that I could make changes to the FE MDE as often as I wanted and be quite confident that the next time someone went to run the app that it would pull in the latest version. For more info on the errors or the Auto FE Updater utility see the free Auto FE Updater utility at http://www.granite.ab.ca/access/autofe.htm at my website to keep the FE on each PC up to date.
3) Now when working on site at a clients I make the updates to the table structure after hours when everyone is out of the system. See HOW TO: Detect User Idle Time or Inactivity in Access 2000 (Q210297) http://support.microsoft.com/?kbid=210297 ACC: How to Detect User Idle Time or Inactivity (Q128814) http://support.microsoft.com/?kbid=128814
However we found that the code which runs on the timer event must be disabled for the programmers. Otherwise weird things start happening when you're editing code.
Also print preview would sometimes not allow the users to run a menu item to export the report to Excel or others. So you had to right click on the Previewed report to get some type of internal focus back on the report so they could then export it. This was also helped by extending the timer to five minutes.
The downside to extending the timer to five minutes was if a person stays in the same form and at the same control for considerable parts of the day, ie someone doing the same inquiries, the routine didn't realize that they had actually done something. I'll be putting in some logic sometime to reset this timer whenever they do something in the program.
4) In reference to another person commenting about scripts and such to update the schema see Compare'Em http://home.gci.net/~mike-noel/CompareEM-LITE/CompareEM.htm. While it has its quirks it does create the VBA code to update tables, fields, indexes and relationships.
Use VBA to unlink and re-link your tables to the new target when switching from dev to prod. It's been to many years for me to remember the syntax--I just know the function was simple to write.
Or use MS-Access to talk to MS-Access through ODBC, or some other data connection that lives outside of the client mdb.
As with all file base databases, you will eventually run into problems with peak usage or when you go over a small magical number somewhere between 2 and 30.
Also, Access tends to corrupt frequently, so backup, compact and repair need to be done on an frequent basis. 3rd party tools used to exist to automate this task.
As far as performance goes, the data is being processed client side, so you might want to use something like netmeter to watch how much data is going over the wire. The same principle about indexing and avoiding table scans apply to file base dbs as well.
Many good suggestions from other people. Here's my 2 millicents worth. My backend data is on server accessed through a Drive mapping. In my case, the Y drive. Production users get the mapping through a login script using active directory. Then the following scenarios are easily done by batch file:
Develop against local computer by doing a subst command in a batch file
run reports against last nights data by pointing Y to the backup server (read only)
run reports against end of month data by pointing to the right directory
test against specialized scenarios by keeping a special directory
In my environment (average 5 simultaneous users, 1000's of rows, not 10,000's.) corruption has occurred, but it's rare and manageable. Only once in the last several years have we resorted to the previous days backup. We use SQL Server for our higher volume stuff, but it's not as convenient to develop against, probably because we don't have a SQL admin on site.
You might also find some of the answers to this question (how to extract schemas from access) to be useful as well. Once you've extracted a schema using one of the techniques that were suggested you gain a whole range of new options like the ability to use source control on the schemas, as well as being able to easily build "clean" testing environments.
Edit to respond to comment:
There's no easy way to source control an Access database in it's native format, but schema files are just text files like any other. Hence, you can check them in and out of the source control software of your choice for easy version control/rollbacks.
Or course, it relies on you having a series of scripts set up to re-build your database from the schema. Once you do, it's normally fairly trivial to create an option/alternative version that rebuilds it in a different location, allowing you to build test environments from any previous committed version of the schema. I hope that clarifies a bit!
If you want to update the back end MDB schema automatically when you release a new FE to the clients then see Compare'Em http://home.gci.net/~mike-noel/CompareEM-LITE/CompareEM.htm will happily generate the VBA code need to recreate an MDB. Or the code to create the differences between two MDBs so you can do a version upgrade of the already existing BE MDB. It's a bit quirky but works.
I use it all the time.
You need to understand that a shared mdb file for the data is not a robust solution. Microsoft would suggest that SQL Server or some other server based database would be a far better solution and would allow you to use the same access front end. The migration wizard would help you make the changeover if you wanted to go that way.
As another uses pointed out, corruption will occur. It is simply a question of how often, not if.
To understand the performance issues you need to understand that to the server the mdb file with the data in it is simply that, a file. Since no code runs on the server, the server does not understand transactions, record locking etc. It simply knows that there is a file that a bunch of people are trying to read and write simultaniously.
With a database system such as SQL Server, Oracle, DB2. MySQL etc. the database program runs on the server and looks to the server like a single program accessing the database file. It is the database program (running on the server) that handles record locking, transactions, concurrency, logging, data backup/recovery and all the other nice things one wants from a database.
Since a database program designed to run on the server is designed to do that and only that, it can do it far better and more efficently that a program like Access reading an writing a shared file (mdb).
There are two rules for developing against live data
The first rule is . . . never develop
against live data. Not ever.
The second rule is . . .never develop
against live data. Not ever.
You can programatically change the bindings for linked tables, so you can write a macro to change your links when you're deploying a new version.
The application is slow because it's MS Access, and it doesn't like many concurrent users (where many is any number > 1).
I've created a database in access 2007 that needs to be used by 3 users. I'm stuck because I don't know whether to place a copy on each users' computer or to place it on their SQL server. Placing it on the server would mean one access point which is desirable for data consistency but I don't know whether I need ActiveX. Don't know how to use it either. If I place it one each computer how do I work around the master file updates? Can somebody please break it all down, I'm a NEWBIE!!
Your question seems rather confused to me. You mention a SQL Server, but you don't say your application uses SQL Server for its data storage.
Thus, I can only assume that you have a single MDB or ACCDB file with your data tables and forms and reports all in the one file.
The only proper way to distribute this app is:
split it into front end (forms/reports/etc.) with linked tables that point to the back end (data tables only).
place the back end on your file server and relink your tables to point to the new location of the back end.
give a copy of the front end to each of the 3 users, who will run it from their desktop computers. If you're concerned about distributing changes to the front end, something like Tony Toews's front-end updater is very useful.
Others have jumped in to say that you should put the data in SQL Server, but most 3-user Access apps don't need the power of SQL Server. If you're not given administrative permissions on your SQL Server, it could be quite difficult to continue to alter your application's database.
On the other hand, if your database is going to grow to 1GB or more, or if you have strict security requirements, or if the data in your database is so important as to need completely failproof backups, then SQL Server would be a reasonable data store.
For most homegrown apps, not so much.
The "best" way I've worked this out is using Linked Tables in Access to go to SQL Server (since you stated you have that..?).
Using access as a front end in this scenario isn't the best thing you can do, but with 2007, it's a bit better than if you were a few versions back. Check out this article for info on linking Access into SqlServer:
Import or link to SQL Server data
One easy way is to use the EQL Data plugin: http://eqldata.com
That way you can give a copy of the database to each user, but users can sync the database with other users whenever they want. You can also access your tables and queries on the web.