MS Access and Google File Stream - ms-access

Apologies in advance if this is a dumb question, but with Google's release of "File Stream", does anyone know how this would impact MS Access dbs stored on it?
My "setup" is that I have users that are routinely using an AccessDB that was built for them years ago, and I'm trying to replicate it in MS SQL. Not by my choice, the file is stored by the clients on a Google Drive: Which essentially means that I can only look at the vba and do testing when the clients are not using it. The clients also use Google's sync to access the file.
So my question is two-fold. First, if the clients are looking to move to File Stream and asked how this would impact their ability to use the Access file (I have no idea). Second, will File Stream make it possible to have multiple users on a MS database without causing conflicts or problems? Would I still need to make sure that I have exclusive access to the file while making changes to the vba code?
Thanks in advance!
UPDATE: Over 1k visitors with the same question and updating the description as asked by the person who marked this as -1 (now marked -2 without feedback) but the only question answered is that having multiple users simultaneously isn't sound. What remains is why a single user scenario can cause corruption of the file stored on stream: Compact/repair fails at least when the file is large.

Based on experience, you need to make sure only one person has the database open at a time. If two people open the database, then changes will not be saved. Try to find a different solution if possible.

The MSAccess database engine is fundamentally based on the database primitives provided by the MS file system. Including the record read/write/lock primitives. (Bet you didn't even know that MS operating systems had a native database system!).
Access records and tables are NOT filesystem records and tables, BUT -- the Access database system of records and tables are built on top of the native system of record locking. (The native system doesn't, and never had, any thing smaller than file-level authentication and permissions, so Access built a whole new system on top).
That means that any file system, or any network file system redirector, which doesn't support record locking like the MS file system and the SMB protocol, can't support simultanous multi-user access to an Access database.
I'm not familiar with Google FileStream, but I assume that it's a way to access binary objects using a database API? Normally that means the API doesn't look inside the binary object: so it can't be locking individual sections of the file for R or W or RW: that means you can't R part of the object while somebody else W a different part: that means you can't share access. ... and even if File Stream means something different to Google, the chance that they support SMB inside it is slim to none, right?

Related

Why do MS Access front-ends increase in size over time?

I have an MS Access front-end (Oracle back-end) that has 2 linked tables, 2 MS Access queries, and 4 reports.
I've noticed that the .accdb files (stored on users' desktops) get bigger over time. They start out at under 1mb after a compact, and end up being 10-20mb after a few months use.
Why is this? There isn't any data stored in the file, so why does it get bigger over time?
It's because (some) temporary data are created in the frontend. It shouldn't matter at all, except if it disturbs you.
You can avoid that completely by making the frontend file read-only, but usually it pops a warning message when the user launch the frontend. It will force temporary data to be written to separate files.
Another method is to set the frontend to compact before closure. However, that sometimes fail, thus causing more trouble than advantages.
The definitive method to avoid it, is to copy a fresh frontend to user. The user clicks a shortcut to a script that copies the file from the server to a local folder and launch it from the local copy. A script to handle that can be found here:
Deploy and update a Microsoft Access application in a Citrix environment
I had the same problem and this is what I learned :
Front-End file size can increase because of a lot or reason and it is important to verify what is the cause. (Memory Leak, Image Management etc)
A good deployment architecture is important and will help avoid the file to increase over time:
Good Example of deployment architecture
If it is too late and your file have already increased, you can normally return close to the original size with the "Compact and Repair Database" functionality:
Open Access in design mode
Access Section "Database Tools"
Select "Compact and Repair Database"

Sharing control to maintain Access database on One-Drive

We have a central Access database (with smaller peripheral databases attached) that we would like several users not in the same locality to work on through a network. We currently have the databases on OneDrive; we would also like to lock the database when it is being edited.
I see there is a relevant post that is 5 years old on StackOverflow:
Access database sharing strategies
We have the Office 365 version. Would the solution enable us to lock the databases when they are in use? Are there new solutions to help with our task? We are also willing to try other online storage options if they are better than OneDrive.
Thank you in advance.
The post you provide a link to is quote old now, and some of what it says it bang on still, but some of it is a little bit misleading.
Running an access file that is stored on onedrive sounds like a very bad idea to me.
The post mentioned "Windows Terminal Server". This is a good solution as in effect it allows multiple users to open their own copy of an access file that grabs data from a singel access database file stored on the machine they are accessing using WTS. You will need to investigate this more.
That said, I've never used the above.
I wanted to write as you should be aware that Access 2013 can be used with SQL Server to store it data. Some "slightly more expensive subscriptions designed for business" will give the subscribers access to Sharepoint and access 2013 can then be used to create "Access web apps", and Access makes it really easy to store the data on a SQL Server that is managed for you and really simple to use. Users can also enter and view data into what MS call "Access Views" which are essentiall basic access forms that can be used in a web browser.
My gut feeling is that the WTS route will be best for you.
It's worth noting that there can be considerable work to move data from an access file into SQL server using the MS tools. This depends on what features of access you use.

SELECT query is pulling data, source table appears in MSysObjects, Hidden/System are both enabled, but table isn't listed in object browser

I am completely perplexed.
A colleague's got a database issue. I noticed that the (internal) software that created the local database file with the problem, uses programmatic access to MS JET, which meant an easy first step was to see if MS Access (2010) was happy with the database - and then fix, export/import or repair, as a first step.
I copied the stand-alone local Jet data file to a non-networked virtual machine (so no chance of external data), and MS Access opened the db file easily, but I can't make sense of what I'm seeing.
MS Access is configured on that system to show all hidden and system objects, confirmed since the Access system tables in the file are all visible and can be opened. These are my observations:
The object browser lists the usual MS system tables, and a bunch of SELECT queries (which look correct) of the form SELECT (FIELD LIST) FROM (OTHERTABLENAME) WHERE (FIELDNAME=VALUE), nothing more.
The select queries show the usual grid with valid data records when opened, and the data looks correct as well.
No data tables with the given names are showing in the object browser interface.
The given names are listed as objects of the database, in the system table MSysObjects.
So..... the underlying data tables ARE named in MSysObjects, and seem to be true data tables... but they are NOT being listed in the object browser and I can't figure how to open their datasheets (although MS Access' system tables are, and "Show hidden/system" are both enabled)... and the tables surely do exist in the file since an apparent SELECT query is pulling their data from them, and the file is on a clean non-networked machine with no other sources reachable.
Any ideas? I want to check the underlying data but ... whats going on?
When I examined your database, I discovered the reason you can't access the tables normally is because the authors of the internal application which created the db file implemented measures to prevent normal access.
I advise you to contact them and your managers to get authorization and assistance to view the data.
Also, please be cautious with this question. A suspicious person might uncharitably interpret your question as a disguised request for hacking help. Please note I am not accusing you of anything underhanded ... simply asking you to notice how your question might be perceived. And, if that were to happen, I don't know what the consequences would be on Stack Overflow, but I can't imagine it would be good. So please be careful.

How to set up a development environment in MS Access

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).

How can I open an Access DB via ADO so that I can write, but others can only read?

From the documentation, I would expect adModeShareDenyWrite to be the way, but it's not working right.
I'm using an Access database via ADO. My connection string says Mode=8, which is adModeShareDenyWrite. But when I try to delete a row from a table, I get:
Unspecified error, Description:Could not delete from specified tables., Source:Microsoft JET Database Engine
In other words, the setting is preventing ME from updating the database using my OWN connection.
I found a couple other posts on the web reporting the same thing, the adModeShareDenyWrite setting used with Access not working as documented.
I am looking for a solution that doesn't involve an administrator changing permissions. It needs to be something that my program can control.
My motivation here is to minimize the chances of database corruption. One of the causes of mdb file corruption documented by Microsoft is two apps writing to the same db. So, I want to make sure that only one app can have a write connection to the db. Others can read, but should fail when they try to write. Whoever makes a connection first wins.
Cory Trager wrote:
My motivation here is to minimize the
chances of database corruption. One of
the causes of mdb file corruption
documented by Microsoft is two apps
writing to the same db. So, I want to
make sure that only one app can have a
write connection to the db. Others can
read, but should fail when they try to
write. Whoever makes a connection
first wins.
Why are you worrying about it? Jet is by default a multi-user database engine. If somebody else is updating a table, the data pages involved will be locked as read-only (in the state they were before the write began).
There is no realistic reason to fear corruption from mere multi-user interaction. Corruption of Jet databases usually happens because of dropped connections or an interruption of the connection during a write (such as users who force quit an app that is not responding as fast as they want).
I think your fear of corruption is misplaced.
On the other hand, you should still be able to open with an exclusive lock, and I'm not sure why it's not working. Have you considered using DAO instead of ADO to manipulate Jet data? Given that it's the native data interface (instead of a generic interface layer), it ought to be easier.
One solution is to give them access to a copy of the database. They can change whatever they want, but it won't keep past your copying it over with the master.
I suppose you access here an MDB file from a client interface, whatever it is, and others can also connect to the same file at the same time. When you use adModeShareDenyWrite in your connection mode, it means that you can still share the data with others (no locks of any kind on tables or records in the MDB file) but it can't be modified (this is why you get an error).
One solution would be to manage your connection parameters, with something like that:
(where you have a user object with a '.role' property, or anything equivalent ...)
if activeUser.role = "admin" then
m_connectionMode = adModeWrite
else
m_connectionMode = adModeShareDenyWrite
endif
Then you can open your ADO connection with the parameter m_connectionMode. Administrators will be given the right to insert/update/delete while other users will ony be able to view the data. This means you have somewhere in your program, or ideally in a table, some data saying who is what in your application.
EDIT: Following multiples comments with Corey:
You won't be able to do what you want to do in a straight way. My proposal: when the app accesses the database, it checks for a special file in the .mdb folder (whatever the file is).
If this file exists, the app opens a "read-only" connection.
If this file does not exist, the app creates the file (you can create one for example with "transferDatabase") and open a read-write connection. Once you quit the app, destroy the file.
If you have multiple users connecting to an access database across a network you might want to consider upgrading to SqlServer instead of using Access.
Corey Trager wrote:
I am looking for a solution that
doesn't involve an administrator
changing permissions. It needs to be
something that my program can control.
Well, if the problem is due to NTFS permissions being read-only for the user, there isn't a thing you can do to make the MDB writable. You don't specify where the MDB is stored, on a server or on a local hard drive, but in either case, for a user to have WRITE permissions on the MDB, NTFS permissions have to be set to allow it (for a share on a server, it has to be allowed both on the SHARE and on the underlying file). If it's a local file, the best solution is to make sure that you're storing the file in a location in which user-level logons have full WRITE permission. This would be anywhere in the user profile, and just about nowhere else.
That said, I'm not really suggesting that this is the source of your problem (I really can't say one way or the other), just pointing out that if it is the cause, then there's not a damned thing you can do programmatically to work around it.