SMO backup reports can't open backup device (which is a file), Message 3201 - sql-server

This code runs fine on a local SQL Server Express instance:
Dim thisSMOBackup As New Backup()
With thisSMOBackup
.Database = singleDatabase.Name 'This contains the database name
.Action = BackupActionType.Database
.Devices.AddDevice(DatabaseFileName, DeviceType.File)
.Incremental = False
.LogTruncation = BackupTruncateLogType.Truncate
End With
Try
thisSMOBackup.SqlBackup(thisServer) 'thisServer is setup w/ valid connection string and reads back data OK from the SQL server
System.IO.File.AppendAllText(logfileName, singleDatabase.Name & " - backed up")
Catch ex As Exception
System.IO.File.AppendAllText(logfileName, singleDatabase.Name & " - " & ex.InnerException.Message & vbCrLf)
End Try
When I apply the same code to a shared hosting SQL Server, it yields the following inner exception error message:
Cannot open backup device 'D:\aFolderName\aBackupName\theDatabaseName.bak'. Operating system error 3(The system cannot find the path specified.). BACKUP DATABASE is terminating abnormally.
Message #: 3201
There seems to be different ways to connect to the servers. For the SQL Server Express instance, I am using the .ServerInstance property, for the hosted server I am using the .ConnectionString property. Does that have anything to do with how the SMO code functions?
I have read that shared SQL hosting servers can have restrictions that are difficult to get past, but before I give up I wanted to ask for input.
The error itself suggests SMO can't find the location to write the file, but it's there, and I set the security for the folder to "Everyone" with "Full Control". But then errors seem to not always mean precisely what they say. I wondered if there were some other parameters I need to setup for this operation to succeed, or other places to look.

When you're trying to create a backup in your shared hosting environment, the backup file is being written to the file system of that remote server machine (NOT your own, local D: drive!) where your SQL Server is running.
Most likely, the user account that runs the SQL Server remotely just doesn't have permission to write to that directory.
Also: this is a good thing! After all, you wouldn't want a remote server machine which you don't know and have no control over to be able to have direct write access to your own, local machine - now would you?
What you could do (esp. in a corporate environment) is to write backups to a UNC path (\\server\share\path) where both the remote SQL Server machine has write access to, and to which you have at least read access, so that you could go there and copy the .bak files to your local machine as needed. With a commercial hosting company, that option very rarely exists, however....

Related

Connecting to SQL Server in a remote server from Access

We have a Server A and a Server B.
In Server A we have our ERPs made in Access and VBA.
In Server B we have an instance of SQL Server that needs to stay in that server.
Some Access databases need to link to some tables from that SQL Server instance and I don't want the password to be stored in the MSysObjects table, so I cannot manually link the tables checking the save the connection option.
I saved the connection string in a table with password obfuscation. With that connection string I re-link the tables on startup.
The instance is accessed through it's IP, not the name of the instance. If I use the name of the instance it doesn't work.
It works for me but not for other users except one.
The SQL Server instance has been properly configured to allow remote connections, the ports have been opened and rules added to firewall. If it wasn't properly configured it wouldn't work for me and the other user, so I'm pretty confident in that. The same with the connection string and the methods to stablish the connection in Access.
What I've tried:
Installing the SQL Native Client 11.0.
Installing a full SQL Server Express.
Configured the SQL Browser service to star automatically instead of being disabled.
Step 1 did not work for any user. Step 2 did work for one user but not for the rest. Step 3 did not had any effect. For me I had it installed in my machine since forever, so it doesn't apply.
If I try to do the same with a SQL Server instance in our LAN it works for every user, but not when the instance is in a remote server.
Note I have limited knowledge. Maybe I say something that does not make sense.
Ok, a few things:
Installing the SQL Native Client 11.0.
Ok, then you have to re-link the tables - choose the new driver. A refresh of the linked tables is NOT sufficent. And this ALSO means that each work station ALSO now must have native 11 instlled. And if you say decide to link using native 17 (a much newer odbc driver), then AGAIN YOU must install this native driver on each work station. While you can install multiple sql drivers on each workstation, the driver you used to link the tables MUST ALSO be installed and exist on each work station.
Installing a full SQL Server Express.
Why? What would installing a copy of sql server have to do with OTHER sql servers on other machines that you are attempting to connect to? You think installing sql server on a machine effects the sql server running say on amazon.com? So, this move makes no sense at all.
You are attempting to connect to some instance of sql server running on some other computer. Makes no sense nor will it help to install some copy of sql server that you not using, not connecting to, and that has zero to do with this issue.
Configured the SQL Browser service to star automatically instead of being disabled.
Where? The browser service is set to run and startup on the server and SAME machine where sql server is installed and running. So, yes, without question, those two sql servers A, and B most certainly MUST have the sql browser service running. That service is what allows the client computers to connect to that running instance of sql server. In the past, older (previous) versions of sql server would allow a default connection, but now in near all cases, you MUST ensure that the sql browser service is running on that computer that also has the database you are attempting to connect to.
it's worth to note that the instance is accessed through it's IP, not the name of the instance.
No, you likly have this incorrect. There are two part.
The server name - and then the "instance" of sql server running.
While you can swap out (not use) the server name, you STILL WILL NEED to specify the sql server instance.
So, you can use this format:
myservername\SQLEXPRESS
Or, you can replace the server with a IP address, but you STILL NEED the sql server instance. (by default, it is SQLEXPRESS - but you have to check what the instance of sql server database is).
192.168.1.30\SQLEXPRESS
So while you can use IP or server name - it is often more reliable to use the IP address, but that does NOT get you off the hook from having to specify the sql instance you connect to. Again, previous editions of sql server often allowed a "default" instance, and you did not in general have to specify the "instance", but now you do. And to be double clear, when using such a instance, that sql server needs to be running the sql browser service. (in fact, the browser service is what translates the incoming request to the given and correct instance of sql server).
I DON'T want the password to be stored in the MSysObjects table,
You don't have to, and in fact should NOT include the uid/password in your connection string. And in fact ZERO reason exists to do so.
What you do is execute a one time logon, and THEN link the tables without UID/password. This is not only a great idea, but it also means that your uid/password is not included in the connection strings, but also means users can't get at, or even by accident see/get the uid/password.
It also means that say someone where to launch a copy of access, and import the linked tables from this applcation. When they attempt to use the linked tables, they will NOT work.
So, then how do linked tables work without a password? (and this ALSO by the way saves you from having to re-link tables on startup!!!).
The way this works, is you in code execute a one time logon to the server on startup. That means you can either:
Prompt the user for their sql UID/password.
or
Have in code, the uid/password. (or perhaps in a text file y ou read on startup. You can thus hide, or encrypt or whatever for that uid/passwords.
Then in your startup code, you execute a one time logon. Once you done this, then all linked tables will now work - and work without having uid/password.
since you have two servers then you need to execute two logons, one for server A, and one for server B. But, once again, as long as the linked tables exist, then they will work.
Now, there are "longer" articles on how to use this logon idea, and then not have to include, or re-link your tables for the SQL uid/password.
The basic code to execute a logon is like this:
Function TestLogin(strCon As String) As Boolean
On Error GoTo TestError
Dim dbs As DAO.Database
Dim qdf As DAO.QueryDef
Set dbs = CurrentDb()
Set qdf = dbs.CreateQueryDef("")
qdf.connect = strCon
qdf.ReturnsRecords = False
'Any VALID SQL statement that runs on server will work below.
' this does assume user has enough rights to query built in
' system tables
qdf.sql = "SELECT 1 "
qdf.Execute
TestLogin = True
Exit Function
TestError:
TestLogin = False
Exit Function
End Function
Keep in mind, that ONCE you acheived a legal logon, then EVEN addtional logon attempts will return true.
Not usually a big deal, but this means you supply a valid connection to above, and if it logs on and works - then now all your linked tables (without uid/password) will work.
I note the above issue that ONCE you done the logon, then all 2nd or more times running the above will work (even if bad or incorrect!!! - DO NOT forget this tip!!!). (this can confuse the daylights out of a developer, since they execute logon, (or open a table). Then they test above routine with a BAD uid/passwords, and it works!!!
So, you have to EXIT access to clear out the password cache - no other way.
So, keep the above tips in mind.

SQL Server linked server error 7303 to Access database

I've performed multiple searches and read numerous pages and tried loads of different configurations and nothing seems to solve a nuisance problem we have. We have a SQL server (2008 R2 v10.50.4000) that has several linked servers to several different access databases on a different server. They are all set up using UNC paths and they work...for a time.
At some point, something happens and then we can no longer access the databases and the only way I have found to solve this is to restart the SQL server service, which obviously isn't ideal in a production environment. This is the exact error message we get when we try to access it:
OLE DB provider "Microsoft.ACE.OLEDB.12.0" for linked server "HIDDEN" returned message "The Microsoft Access database engine cannot open or write to the file '\servername\path01\path02\path03\databasename.mdb'. It is already opened exclusively by another user, or you need permission to view and write its data.".
Yet it works absolutely fine again if I restart the SQL Server service, so I know the settings are correct. I strongly suspect it has something to do with the Microsoft ACE driver because they all (the Access database linked servers) stop working at the same time - even though they all look at different files.
At this point I'm willing to try anything.

Linked Tables via ODBC / {Sql Server} driver using TCPIP lost between MS Access 2003 restarts for mdb

I have the following set-up causing issues:
MDB or MDE frontend in msaccess 2003 (11.6566.8221) SP2
-- run from server share folder or C:\Development
Microsoft SQL Server Express Edition with Advanced Services (9.00.5000.00)
Operating System ("server"): Microsoft Windows NT 5.1 (2600) = Windows XP
I run and debug the MDB and MDE on my development machine (which is the same as the "server") connecting to it using the same Linked Table connections derived from a file DSN.
I take and run the MDB or MDE to another client (mixed client enviroment in the hospital) and it hangs and complains about odbc--connection error on the first call to a table (which is a DLookup in the start up code)
I stop the code, unhide the Database window, and
I re-link all the tables using the File DSN I am
carrying around on my USB drive (same as on the development machine)
Note: the same setting in my File DSN re-creating as a new FileDNS on client = success)
browing all the tables (opening them in Table view from Access Table tab) = works
running all the forms again = works
system runs like normal
** NOW **
I save the MDB again, close the MDB (leaving ACCESS open), open the MDB again
- everything works fine
I now close Access completely (no longer running), open access, and open the mdb
-- error now happens, and any attemp to view a linked table I get the same error
Posible hint: The error message is unusual:
Runtime Error '3151'
ODBC--connection to 'SqlServerSAH0048645' failed
The following does work
- open the file with Startup option set to open "UserValidate" form
- in OnLoad event call ResetDefaultconnections (using down DNSless code I found)
- reset all TableDefs.connection strings to:
strConnectionString = "ODBC;DRIVER={SQLServer} ;Description=RAHCC_DB; SERVER=tcp:10.19.54.64,1500; UID=RAHCC_User; PWD=XXXXXXx; APP=MSACCESS; WSID=SAH0034510; DATABASE=RAHCC_DB"
delete and then add new tabledef records for each linked table
continue to open the form ---> everthing seems to work.
BUT.. as soon as I close access, and re-open --> doesn't work again.
Note
- I am restricted to what I have (is Sql Server is installed on all clients)
- I am restricted to a connection using the Sql Server driver
- I am using Sql Server authorisation
cheers,
JonHD

What state is my SQL server database in when msdeploy fails on user creation?

I am using msdeploy (version 2) to transfer a database from machine A to machine B.
On in the database on machine A there are some users that do not exist on machine B, thus the transfer (partially) fails with the message:
Error Code: ERROR_SQL_EXECUTION_FAILURE
More Information: An error occurred during execution of the database script.
The error occurred between the following lines of the script: "3" and "5".
The verbose log might have more information about the error.
The command started with the following: "CREATE USER [someDomain\someUser] FOR LOGIN [someDomain"
Windows NT user or group 'someDomain\someUser' not found.
Check the name again. http://go.microsoft.com/fwlink/?LinkId=178587
The database seems to be transfered, except for the user creation. Does anyone know what state the database is in after this failure?
Is there any way I can transfer the database without the users (or better without specific users) using msdeploy?
Web Deploy uses SMO (SQL Management Objects) to script out and apply the scripts for SQL databases, and exposes most of the SMO settings with the dbfullsql provider (so, most of these options: http://msdn.microsoft.com/en-us/library/microsoft.sqlserver.management.smo.transfer_properties.aspx). If you want to skip the users due to this kind of login-not-exists or user-not-found error, you should be able to do this by adding the scripting option: copyAllUsers=false to the source of the sync. For example:
msdeploy.exe -verb:sync -source:dbfullsql="Data Source=.\SQLExpress;Initial Catalog=MySourceDb;User Id=localUser;Password=LocalPass",copyAllUsers=false -dest:dbfullsql="Data Source=RemoteSQLServer;Initial Catalog=MyDestDb;User Id=remoteUser;Password=RemotePass"
Incidentally, I am surprised you note the db appears to have been sync'd - I would expect this is not actually the case. If you have the permissions for it, Web Deploy will create the database if it did not already exist when it initially tries to make the connection, but your failure occurred very early in the script execution, and I believe Web Deploy dbfullsql syncs are transacted by default (the db creation is separate from the script execution and is not transacted). Thus the db may exist where it did not pre-sync, but I wouldn't expect the data to be present in it.

Why is it such a mission to backup a SQL Server 2008 Express database?

I wouldn't describe myself as afraid of change - but afraid of new technologies? YES INDEED! Technologies from operating systems, to database servers just seem to become bugged, inefficient and backward the further they "progress"
MSDE 2000 (what they might call "SQL 2000 Express" in today's world)
BACKUP [MyDatabase] TO FILE 'c:\backups\mybackup.backup'
SQL 2008 EXPRESS
Wait up! Its a 'user instance' - to back it up we need to attach it to a server instance
Wait up! To attach it we need SQL Management Studio Express (78MB download)
Wait up! When we login to our .\SQLEXPRESS server instance and try to attach our database it gives us an error that literally looks like a bug in our homebrew dev project:
TITLE: Microsoft SQL Server Management Studio
Cannot show requested dialog.
------------------------------ ADDITIONAL INFORMATION:
Parameter name: nColIndex Actual value
was -1.
(Microsoft.SqlServer.GridControl)
Can someone explain how to backup a user instance of a SQL Server 2008 Express database in T-SQL code?
(sorry if this comes across like a flame at ummmm, Microsoft - I'm actually a huge fan of theirs. Just really angry about things like this! please don't vote me down...)
Um, if it's a user instance, then the simplest backup strategy is to copy the file. (whilst it's not connected to SQL Server).
If you need a more comprehensive backup strategy (e.g. transactional backups), then you really should be looking at a more comprehensive database (e.g. a "normal" one attached to a full SQL Server instance)
SOME KEY TIPS TO NOTE WHEN TRYING TO ACHIEVE USER INSTANCE BACKUP
a.) Connecting
Your connection string should look like this:
Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\MyDatabase.mdf;Integrated Security=True;User Instance=True;Database=MyDatabaseAlias
It is essential that your connection string gives the connection an alias Database=MyDatabaseAlias - this alias cannot be duplicated concurrently on the same machine or your connection may fail.
b.) Backing Up
As pointed out above, the Transact SQL to backup a database is the same on SQL MSDE/2000/2005/2008/R2 - once you have your database attached and aliased!
BACKUP DATABASE MyDatabaseAlias TO DISK = 'c:\backups\mydatabase_20101117.backup'
Whats truly amazing is the bull$h!t errors you can get because your connection string doesnt have the alias Database=MyDatabaseAlias part.
e.g. Unable to open the physical file 'c:\Code\MyProject\App_Data\MyDatabase.mdf' Operating system error 32: "32(The process cannot access the file because it is being used by another process.)".BACKUP DATABASE is terminating abnormally.
c.) Restoring
USE [master]; RESTORE DATABASE MyDatabaseAlias FROM DISK = 'c:\backups\mydatabase_20101117.backup' WITH REPLACE
Do not forget the all essential USE [master]; at the beginning of this statement (and note that its all on one line for those executing the command from a DataContext or similar) If you do, it wont be able to overwrite the existing database because you'll still be connected to it.
Once again, the assortment of totally misleading errors you might receive here, due to an invalid connection string, is endless.

Resources