Override SSDT publish profile ConnectionString - sql-server

I am using the following command to generate to publish database changes using SSDT:
"C:\Program Files\Microsoft SQL Server\150\DAC\bin\SqlPackage.exe" /Action:Publish /sf:DB.dacpac /Profile:publish.xml
I would like to supply database connection string as an argument instead of using a hard coded connection string from publish.xml. Is there anyway I can override it?
I tried:
"C:\Program Files\Microsoft SQL Server\150\DAC\bin\SqlPackage.exe" /Action:Publish /sf:DB.dacpac /Profile:publish.xml /TargetConnectionString:$ConnectionString
where $ConnectionString is an argument from Jenkins. However, it still uses ConnectionString from publish.xml.

I had a quick look at the source code with reflector (Microsoft.Data.Tools.Schema.CommandLineTool.ValidationUtil) and what happens is that TargetConnectionString is read from the command line, then after that the value in the publish profile overwrites the value - that can't be changed I am afraid.
The interesting thing is that after it has the connection string from either /TargetConnectionString or the publish profile it then applies the individual properties such as /TargetDatabaseName so i think (untested but looks good from the code) if instead of passing /TargetConnectionString you pass the individual components such as:
/TargetUser, /TargetPassword, /TargetDatabaseName, /TargetServerName, etc.
Then I think it will override the connection string in the publish profile, it is quite hard to read so let me know how you get on!
ed

Related

Read file in SSIS Project into a variable

My SSIS projects tend to run queries that require changes as they move between environments, like the table schema might change or a value in the Where clause. I've always either put my SQL into a Project Parameter, which is hard to edit since formatting is lost, or just put it directly into the Execute SQL Task/Data Flow Source then manually edited it between migrations which is also not ideal.
I was wonder though if I added my SQL scripts to files within the project, can these be read back in? Example if I put a query like this:
select id, name from %schema%.tablename
I'd like to read this into a variable then it's easy to use an expression as I do with Project Parameters to replace %schema% with the appropriate value. Then the .sql files within the project can be edited with little effort or even tested through an Execute SQL Task that's disabled/removed before the project goes into the deployment flow. But I've been unable to find how to read in a file using a relative path within the project. Also I'm not even sure these get deployed to the SSIS Server.
Thanks for any insight.
I've added a text file query.sql to an SSIS (SQL 2017) Project in Visual Studio, bit I've found no way to pull the contents of query.sql into a variable.
Native tooling approach
For an Execute SQL Task, there's an option to source your query directly from a file.
Set your SQLSourceType to File Connection and then specify a file connection manager in the FileConnection section.
Do be aware that while this is handy, it's also ripe for someone escalating their permissions. If I had access to the file the SSIS package is looking for, I can add a drop database, create a new user and give them SA rights, etc - anything the account that runs the SSIS package can do, a nefarious person could exploit.
Roll your own approach
If you're adamant about reading the file yourself, add two Variables to your SSIS package and supply values like the following
User::QueryPath -> String -> C:\path\to\file.sql
User::QueryActual -> String -> SELECT 1;
Add a Script Task to the package. Specify as a ReadOnly variable User::QueryPath and specify as a ReadWrite variable User::QueryActual
Within the Main you'd need code like the following
string filePath = this.Dts.Variables["User::QueryPath"].Value.ToString();
this.Dts.Variables["User::QueryActual"].Value = System.IO.File.ReadAllText(filePath);
The meat of the matter is System.IO.File.ReadAllText. Note that this doesn't handle checking whether the file exists, you have permission to access, etc. It's just a barebones read of a file (and also open to the same injection challenges as the above method - just this way you own maintaining it versus the fine engineers at Microsoft)
You can build your query by using both Variable and Parameter.
For example:
Parameter A: dbo
Build your variable A (string type) as : "Select * FROM server.DB." + ParameterA + ".Table"
So if you need to change the schema, just change the parameter A will give you the corresponding query in variable A.

"Cannot attach the file as database" error when installing my Code First ClickOnce app

I'm building a WPF application, using EF Code First.
The application seems to work fine while debugging, but when i publish and install it, using ClickOnce, i get this error:
Cannot attach the file [path & filename] as database
I've tried:
checking my connection string using VS Server Explorer
(Cannot attach the file as database / The underlying provider failed on Open)
changing the name of the DB in the connection string
removing tags like AttachDbFilename from the connection string
using sqlcmd to unregister the DB
(http://www.eidias.com/Blog/2013/1/7/error-connecting-to-localdb-after-mdf-and-ldf-files-are-deleted)
deleting the localdb instance
(http://arabic2000.com/blog/index.php/2013/11/localdb-attach-problem-in-visual-studio-2013/)
deleting the DB using VS' SQL Server Object Explorer
simply omitting the connection string, but then i get a different error:
{"Expansion of |DataDirectory| failed while processing the connection string.
Ensure that |DataDirectory| is set to a valid fully-qualified path."}
(there is, however, no mention of |DataDirectory| in my code, except for a commented out connection string)
using DropCreateDatabaseIfModelChanges, or even DropCreateDatabaseAlways, instead of CreateDatabaseIfNotExists
On my home PC, i've had to set the app to not look for updates, as i don't have a network to put the installation folder on.
When i publish, install and run the app here, i get no errors - but all the app seems to do is run in the background until i kill it's process. The UI never shows.
UPDATE:
Meanwhile, i've deleted the DB using SQL Server Management Studio, and that seems to have helped some.
if i don't use a connection string, i get the |DataDirectory| error:
Expansion of |DataDirectory| failed while processing the connection string. Ensure that |DataDirectory| is set to a valid fully-qualified path.
if i subsequently run the app in debug mode (which makes EF create the DB), then run (or re-install) the app, i get this error:
no process at the other end of the pipe
if i subsequently delete the DB (that was created during the debug run in the step above) using SQL Server Management Studio, and run the installed app again, again i get the |DataDirectory| error.
even if i DO use a connection string, specifying an absolute path, i get the |DataDirectory| error.
if i subsequently run the app in debug mode (which makes EF create the DB), then run (or re-install) the app, i get the Cannot Attach the file as database error again.
if i subsequently delete the DB (that was created during the debug run in the step above) using SQL Server Management Studio, and run the installed app again, again i get the |DataDirectory| error.
UPDATE 2:
I got the app working on my home PC.
All it took was... not to use the shortcut ClickOnce added to the Start menu, but run the .exe itself instead.
ClickOnce still doesn't show any notifications once the install is started though, and still fails to launch the app once it's done.
I don't know whether this "fix" will work at work aswell, and won't be able to try it there till tuesday - but i'll keep you posted.
I did briefly try it there, and got this error:
Could not load file or assembly 'EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' or one of its dependencies
... but i may well have used a dated copy of the .exe, as i was in quite a rush.
UPDATE to this answer: i've found a fix:
my trouble seems to have been caused by a faulty connection string:
<add name="4.Data.DienstreisDBContext" connectionString="Data Source=(LocalDb)\v11.0" providerName="System.Data.SqlClient" />
the fault is in the name tag. it should simply say, "DienstreisDBContext" (thereby omitting the name of the folder in which i stored my DBContext class).
I've found a work around:
If i ignore the errors during installation, and use the .exe instead of the Start Menu shortcut ClickOnce generated, my application seems to run fine.
Sadly, this means updating my application won't be as easy as ClickOnce is supposed to make it.

Open Alternate Extension in 'Single Instance' of SQL Server Management Studio

I know how to add additional extensions to SQL Server Management Studio, to have them treated just like .sql files. But, when opening them, a new instance of Management Studio is created.
I also see numerous issues posted about double clicking on .SQL files and getting them to open in the existing instance of SQL server. This already works for me.
What doesn't work is the additional extensions I have added. I'm using .PRC. All of the fixes propose changing various registry settings, all which are related to the default .sql extension.
I don't see see how any of these fixes can be applied to make other extensions work or if there is anything else I can do to solve this?
EDIT:
What i've done so far...
Copied over all the same settings from [HKEY_CLASSES_ROOT.sql] to [HKEY_CLASSES_ROOT.prc].
Checked all the settings mentioned in the article on sql server central to fix this issue for .SQL extensions.
Configured SSMS file type .PRC with editing experience "SQL Query Editor".
I even tried creating a batch file to open the file for me:
"c:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\VSShell\Common7\IDE\ssms.exe" /dde %1
Even the 4th thing I tried opens a new instance, although this is the same call that is configured in the registry for sqlweb.sql.9.0.
I resolved problem of opening PRC file by double click. I simply exported this key from regedit
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.sql
Modified this file to look like this
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.PRC]
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.PRC\OpenWithList]
"a"="ssms.exe"
"MRUList"="a"
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.PRC\OpenWithProgids]
"ssms.sql.11.0"=hex(0):
"ssms.sql.12.0"=hex(0):
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.PRC\UserChoice]
"Progid"="ssms.sql.12.0"
And applied it over registry. The original PRC key I backuped and removed from registry before I applied that new keys. Now PRC file is opened by double click on PRC file in opened instance of SSMS.
But highlighting doesn't work still for me :(
You seem to be going through a lot of hassle to deal with your source control system. Have you considered making your source control system recognize a different extension for procedures, tables, views, etc. which will prevent you having to make these registry changes on every developer's computer?
.proc.sql -> stored procedure
.view.sql -> view
.fn.sql -> function
etc. etc. Surely your source control system can handle longer extensions that contain ., and now Management Studio will behave properly with all your file types.

How to create Log file in SSIS

I want to create a log file in SSIS. I know how to create through management studio, but I wanted to run my SSIS package through Command Prompt.
Can you help me find the Windows commands for that?
You can use the /L option, as documented here; however, you can also set Logging up in a much easier and finer way through the SSIS>Logging menu in Visual Studio.
Cheers,
Eric
In your SSIS you need to create and configure an SSIS Log provider before you can use it. Look into link text for more info.
You need to set up the a new connection string inside of Business Intelligence Development Studio (BIDS). where you have to specify the path of Log file...i mean here path will be D:\Sample_Examples\Log.log... and name of the connection manager will be Log.log
so now the command prompt will get changed into
dtexec /f "C:\\Package.dtsx" /l "DTS.LogProviderTextFile";"Log.log"
instead of
dtexec /f "C:\\Package.dtsx" /l "DTS.LogProviderTextFile;D:\Sample_Examples\Log.log"
we cant specify a direct path after DTS.LogProviderTextFile...because of that only i got error...
Thank you very much for the suggestions...
You can do this another way, without going into your SSIS package.
Create a batch file and run DTEXEC in a new instance of CMD, i.e.:
CMD /C DTEXEC your package and args > log file
When you do this, you can run this batch file and get your log file.
See http://richarddingwall.name/2009/01/26/capture-the-output-from-a-scheduled-task/ for more details
Yes, you have to create a connection manager for the log provider; however; there is no documentation on how to do this if you are using a custom log provider.

Running a SQL install script with SMO. Alternative solutions needed

I've got a web application that uses Microsoft Sql Management Objects (SMO) dll's. I'm wondering how I go about redistributing the libraries for a remote machine.
As I understand it, these come with SQL server or Sql express - which isn't on the remote (shared) webserver. Asking the host to install them, is probably out of the question, so is it possible to dynamically load them?
See below error-
Could not load file or assembly 'Microsoft.SqlServer.Smo, Version=9.0.242.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91' or one of its dependencies. The system cannot find the file specified.
Alternatively, if anyone can provide a workaround for the below snippet that would also be useful. The script variable is a SQL install script which has been read to the end. The nice thing about this is the outputting of each of the execute strings from SQL. I could of course just execute it all in one chunk, but that provides no visual feedback to the user line by line, that the sql is executing ok.
Is there a stored procedure that could perform this sort of thing? Or an alternative way to execute an install script without full permissions.
Dim connection As New SqlConnection(Me.ConnectionString)
connection.Open()
connection.Close()
Dim server As New Server(New ServerConnection(connection))
server.ConnectionContext.SqlExecutionModes = SqlExecutionModes.ExecuteAndCaptureSql
Dim commands As StringCollection = server.ConnectionContext.CapturedSql.Text
server.ConnectionContext.ExecuteNonQuery(script, ExecutionTypes.ContinueOnError)
Dim s As String
For Each s In server.ConnectionContext.CapturedSql.Text
AppendMessages(s)
Next
http://www.mattberther.com/2005/04/11/executing-a-sql-script-using-adonet/
from
http://coolthingoftheday.blogspot.com/2006/11/execute-t-sql-scripts-with-gos.html
Was what I was looking for, and did the trick.
you can try using sqlcmd utilty that comes with sql server
No, you can't dynamically load them, and no, you can't install them without permissions. Sorry about that, but no dice there.

Resources