Configure Slick with Sql Server - sql-server

I have a project that is currently using MySQL that I would like to migrate to SQL Server (running on Azure). I have tried a lot of combinations of configurations but always get the same generic error message:
Cannot connect to database [default]
Here is my latest configuration attempt:
slick.dbs.default.driver = "com.typesafe.slick.driver.ms.SQLServerDriver"
slick.dbs.default.db.driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver"
slick.dbs.default.db.url = "jdbc:sqlserver://my_host.database.windows.net:1433;database=my_db"
slick.dbs.default.db.user = "username"
slick.dbs.default.db.password = "password"
slick.dbs.default.db.connectionTimeout="10 seconds"
I have the sqljdbc4.jar in my lib/ folder.
And have added the following to my build.sbt
libraryDependencies += "com.typesafe.slick" %% "slick-extensions" % "3.0.0"
resolvers += "Typesafe Releases" at "http://repo.typesafe.com/typesafe/maven-releases/"
Edit: I can connect from this machine using a GUI app, so the issue is not with any of the network settings.

Edit: 5/30/2017
After the release of Slick 3.2 the driver is now in the core suite, these are examples of Configs with 3.2
oracle = {
driver = "slick.jdbc.OracleProfile$"
db {
host = ${?ORACLE_HOST}
port = ${?ORACLE_PORT}
sid = ${?ORACLE_SID}
url = "jdbc:oracle:thin:#//"${oracle.db.host}":"${oracle.db.port}"/"${oracle.db.sid}
user = ${?ORACLE_USERNAME}
password = ${?ORACLE_PASSWORD}
}
}
sqlserver = {
driver = "slick.jdbc.SQLServerProfile$"
db {
host = ${?SQLSERVER_HOST}
port = ${?SQLSERVER_PORT}
databaseName = ${?SQLSERVER_DB_NAME}
url = "jdbc:sqlserver://"${sqlserver.db.host}":"${sqlserver.db.port}";databaseName="${sqlserver.db.databaseName}
user = ${?SQLSERVER_USERNAME}
password = ${?SQLSERVER_PASSWORD}
}
}
End Edit
I only have experience with the oracle config but I believe it is fairly similar. You are missing the critical $ at the end of the default driver. Also you will need to make sure your SBT project recognizes the lib
This first code snippet should be in application.conf or whatever file you are using for your Configuration
oracle = {
driver = "com.typesafe.slick.driver.oracle.OracleDriver$"
db {
host = ""
port = ""
sid = ""
url = "jdbc:oracle:thin:#//"${oracle.db.host}":"${oracle.db.port}"/"${oracle.db.sid}
user = ${?USERNAME}
password = ${?PASSWORD}
driver = oracle.jdbc.driver.OracleDriver
}
}
This second section is in my build.sbt . I put my oracle driver in the base folder in the /.lib, although their may be a better way.
unmanagedBase := baseDirectory.value / ".lib"
Finally to make sure the config is loading properly. Slick default seems to misbehave, so hopefully you get a right answer, rather than a what works for me answer. However utilizing my config above I can then load that using the last snippet. I found this in an example of a cake implementation and it has worked very well in multiple projects.
val dbConfig: DatabaseConfig[JdbcProfile] = DatabaseConfig.forConfig("oracle")
implicit val profile: JdbcProfile = dbConfig.driver
implicit val db: JdbcProfile#Backend#Database = dbConfig.db
This allows you to use the database, the driver for imports and will fail on compile if your configuration is wrong. Hope this helps.
edit : I finished and realized you were working with Azure so make sure that you can fully connect utilizing the same settings from the same machine utilizing a client of your choice. To make sure all firewall and user settings are correct and that the problem truly lies in your code and not in your system configuration.
edit2: Wanted to make sure I didn't give you bad advice since it was an Oracle Config so I set it up against and AWS SQL Server. I utilized the sqljdbc42.jar that is given by Microsoft with their jdbc install. Put that in the .lib and then I had a configuration like follows. As in the upper example you could instead use Environmental variables but this was just a quick proof of concept. Here is a Microsoft SQL Server Config I have now tested to confirm works.
sqlserver = {
driver = "com.typesafe.slick.driver.ms.SQLServerDriver$"
db {
driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver"
host = ""
port = ""
databaseName = ""
url = "jdbc:sqlserver://"${sqlserver.db.host}":"${sqlserver.db.port}";databaseName="${sqlserver.db.databaseName}
user = ""
password = ""
}
}

Related

Azure Terraform import bacpac into SQL Server with public network access disabled

I have a SQL Server in Azure with public network access disabled
resource "azurerm_mssql_server" "sql_server" {
name = var.db-server-name
resource_group_name = var.resource_group
location = var.location
version = "12.0"
administrator_login = local.login
administrator_login_password = local.password
minimum_tls_version = "1.2"
public_network_access_enabled = false
tags = var.tags
}
For accessing the server, I am creating a private endpoint:
resource "azurerm_private_endpoint" "sqlserver_private_endpoint" {
name = "sqlserver-private-endpoint"
location = var.location
resource_group_name = var.resource_group
subnet_id = azurerm_subnet.db_subnet.id
private_service_connection {
name = "sqlserver-psc"
is_manual_connection = false
private_connection_resource_id = azurerm_mssql_server.sql_server.id
subresource_names = ["sqlServer"]
}
tags = var.tags
}
I am then trying to create/import a database from Blob-Storage
resource "azurerm_mssql_database" "sql_server_database" {
name = var.db-name
server_id = azurerm_mssql_server.sql_server.id
collation = "SQL_Latin1_General_CP1_CI_AS"
auto_pause_delay_in_minutes = 60
max_size_gb = 32
min_capacity = 0.5
read_replica_count = 0
read_scale = false
sku_name = "GP_S_Gen5_1"
zone_redundant = false
import {
storage_uri = var.storage-url
storage_key = var.storage-key
storage_key_type = "StorageAccessKey"
administrator_login = azurerm_mssql_server.sql_server.administrator_login
administrator_login_password = azurerm_mssql_server.sql_server.administrator_login_password
authentication_type = "Sql"
}
}
With this setup, I get the following error
Error: while import bacpac into the new database test-db (Resource Group Test-dev): Code="ImportExportJobError" Message="The ImportExport operation with Request Id '1b005b56-bccd-4484-a5e0-c2495834798a' failed due to 'The SQL instance is inaccessible because the public network interface is denied (Error 47073). Please enable public network access on the SQL Server or configure Import/Export to use Private Link per https://docs.microsoft.com/en-us/azure/azure-sql/database/database-import-export-private-link.'."
with module.sql_server.azurerm_mssql_database.sql_server_database, on Modules\SqlServer\main.tf line 69, in resource "azurerm_mssql_database" "sql_server_database":
69: resource "azurerm_mssql_database" "sql_server_database" {
This error makes sense as I have set public_network_access_enabled = false on my SQL Server.
For security reasons I would not like to set
public_network_access_enabled = true
so my question would be: is there a possibility to import the database without enabling network access on the server?
Here I found a way to import the database using PowerShell, which should create a Privatelink for importing, but using this the Database would not be created using Terraform and would not be managed through the Terraform-State...
So does someone know of a way to import the database using Terraform with public_network_access_enabled = false?
(AzureRM Provider Version: 3.31)
Using Private Link for importing seems to be still in Preview. Preview features are rarely (or never) supported with Terraform so I would search alternatives for now.
I personally would create the database with Terraform and then manually (or with some CI/CD magic) import the required data. Generally Terraform is a bit clunky tool in managing what happens inside a database and I personally like using other tools for it.

Ktor with Gradle run configuration "Could not resolve substitution to a value" from environment variables

I have set up a server in Ktor with a Postgres database in Docker, but figured it would be useful to be able to develop the server locally without rebuilding the docker container each time.
In application.conf I have
// ...
db {
jdbcUrl = ${DATABASE_URL}
dbDriver = "org.postgresql.Driver"
dbDriver = ${?DATABASE_DRIVER}
dbUser = ${DATABASE_USER}
dbPassword = ${DATABASE_PASSWORD}
}
and in my DatabaseFactory I have
object DatabaseFactory {
private val appConfig = HoconApplicationConfig(ConfigFactory.load())
private val dbUrl = appConfig.property("db.jdbcUrl").getString()
private val dbDriver = appConfig.property("db.dbDriver").getString()
private val dbUser = appConfig.property("db.dbUser").getString()
private val dbPassword = appConfig.property("db.dbPassword").getString()
fun init() {
Database.connect(hikari())
transaction {
val flyway = Flyway.configure().dataSource(dbUrl, dbUser, dbPassword).load()
flyway.migrate()
}
}
private fun hikari(): HikariDataSource {
val config = HikariConfig()
config.driverClassName = dbDriver
config.jdbcUrl = dbUrl
config.username = dbUser
config.password = dbPassword
config.maximumPoolSize = 3
config.isAutoCommit = false
config.transactionIsolation = "TRANSACTION_REPEATABLE_READ"
config.validate()
return HikariDataSource(config)
}
suspend fun <T> dbQuery(block: () -> T): T =
withContext(Dispatchers.IO) {
transaction { block() }
}
}
I have edited the Gradle run configuration with the following environment config:
DATABASE_URL=jdbc:h2:mem:default;DATABASE_DRIVER=org.h2.Driver;DATABASE_USER=test;DATABASE_PASSWORD=password
When I run the task I get this error: Could not resolve substitution to a value: ${DATABASE_URL}, but if I set a breakpoint on the first line (private val appConfig) and evaluate System.getenv("DATABASE_URL") it is resolved to the correct value.
My questions are:
Why does this not work?
What is the best (or: a good) setup for developing the server without packing it in a container? Preferably without running the database in another container.
You need to specify:
appConfig.property("ktor.db.jdbcUrl").getString()
I found that setting environment variables for the task in gradle.config.kts works:
tasks {
"run"(JavaExec::class) {
environment("DATABASE_URL", "jdbc:postgresql://localhost:5432/test")
environment("DATABASE_USER", "test")
environment("DATABASE_PASSWORD", "password")
}
}
(source: Setting environment variables in build.gradle.kts)
As for why my initial approach only works in debug mode I have no idea.
As for question #2 I have a suspicion that H2 and Postgres could have some syntactic differences that will cause trouble. Running the database container in the background works fine for now.
As answered by #leonardo-freitas we need to specify ktor. first before accessing application.conf properties.
environment.config.property("ktor.db.jdbcUrl").getString()
This is missing on the official doc as well https://ktor.io/docs/jwt.html#validate-payload
I experienced the same problem. I had to manually restart the IntelliJ (NOT via File). Simply closed the IDE, and then turned it on again. Also, check that your environment variable is permanent.

Trying to connect to SQL Server database using TestComplete 11, but I am getting an error

I am trying to connect to a SQL Server database using TestComplete 11, but I am getting an error
Provider cannot be found. It may not be properly installed.
I have added the ODBC Driver, you can look at the screenshot
Below is the code I am using, please let me know how can I fix it.
AConnection = ADO.CreateADOConnection();
// Specify the connection string
var AConnection = ADO.CreateADOConnection();
AConnection.ConnectionString = "Provider=SQLDriver; Server = KEOUS-SQL\MSSQLSERVER01,1724; Database=K212.HrPayroll.ThamesValley.Hina;user id = sql.server;password=sql.server";
// Suppress the login dialog box
AConnection.LoginPrompt = false;
AConnection.Open();
// Execute a simple query
RecSet = AConnection.Execute_("SELECT * FROM EC_GROUP WHERE EMP_GROUP_CODE = 'ADMIN1'");
// Iterate through query results and insert data into the test log
RecSet.MoveFirst();
while(! RecSet.EOF)
{
Log.Message(RecSet.Fields.Item("EC_GROUP").Value, RecSet.Fields.Item("EMP_GROUP_CODE").Value);
RecSet.MoveNext();
}
AConnection.Close();
As TestComplete is a 32 bit application, it will only work with strictly 32 bit ODBC drivers. Use a data source that is configured with a 32 bit driver.

JDBC DriverManager trying to use non specified Oracle driver

I am trying to connect to an Oracle Database using the java.sql.DriverManager in a JSF application. I am using a Tomcat v7 with ojdbc5.jar.
I have a very simple sample project that consists of nothing else than this piece of java code:
String url = "jdbc:oracle:thin:#DBSERV:DBPORT:DBSID";
String user = "account_admin";
String password = "my_assword";
Connection connection = null;
try {
Class.forName("oracle.jdbc.OracleDriver");
connection = DriverManager.getConnection(url, user, password);
connection.close();
} catch ..
...
Executed I get the following error:
java.lang.NoClassDefFoundError: Could not initialize class oracle.jdbc.driver.OracleDriver
Infact the class specified there "oracle.jdbc.driver.OracleDriver" is deprecated...and I can't change the Tomcat configuration. Therefore I specified "oracle.jdbc.OracleDriver" which loads just fine.
So the question is: Why does the DriverManager tries to load the "wrong" oracle driver, although I am loading another one?
I also tried as an alternative to Class.forName the following:
DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
That does not change anything though. I also checked for the registered drivers in the following way:
Enumeration<Driver> driverList = DriverManager.getDrivers();
while(driverList.hasMoreElements()){
Driver driver = driverList.nextElement();
System.out.println(driver.getClass().toString());
}
The output:
class sun.jdbc.odbc.JdbcOdbcDriver
class oracle.jdbc.OracleDriver
So the desired driver seems to be registered, no trace of the deprecated "oracle.jdbc.driver.OracleDriver".
Thank you for any help
My problem just disappeared when I restarted the container. I can't explain why that is though.

Not able to deploy database on App Harbor

I am trying to deploy an instance which is getting the following build error on App Harbor
Build FAILED.
"D:\temp\gcp22bmp.ggi\input\src\ShareBill.sln" (default target) (1) ->
"D:\temp\gcp22bmp.ggi\input\src\Sharebill.Database\Sharebill.Database.dbproj" (default target) (5) ->
D:\temp\gcp22bmp.ggi\input\src\packages\TeamData\Microsoft.Data.Schema.SqlTasks.targets(5,3): error MSB4019: The imported project "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\TeamData\Microsoft.Data.Schema.TSqlTasks.targets" was not found. Confirm that the path in the <Import> declaration is correct, and that the file exists on disk. [D:\temp\gcp22bmp.ggi\input\src\Sharebill.Database\Sharebill.Database.dbproj]
0 Warning(s)
1 Error(s)
I know this is because the sql targets that are generally present here - C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\TeamData
are not present on the deployment server.
What should I do to deploy the data base now? Is there any other way to deploy the database. I have not used code first in EF, but I still want to have db migrations automatically applied.
I am assuming that if i get the db project running it would automatically find the schema differences and apply the changes to the database.
I host a project on AppHarbor and use FluentMigrator to deploy my database changes.
It is really easy to implement, just follow the documentation you can use their fluent interface or even just use it to execute sql.
As an example I run the following from my Application_Start of my Global.asax.cs - just put you migrations in the same assembly as the NOP MigrationMarker class:
const string connectionString = #"Data Source=localhost, 1433;Initial Catalog=testdb;Integrated Security=SSPI;";
Announcer announcer = new TextWriterAnnouncer(s => System.Diagnostics.Debug.WriteLine(s));
announcer.ShowSql = true;
var assembly = Assembly.GetAssembly(typeof(MigrationMarker));
var migrationContext = new RunnerContext(announcer);
var options = new ProcessorOptions
{
PreviewOnly = false, // set to true to see the SQL
Timeout = 60
};
var factory = new SqlServer2008ProcessorFactory();
var processor = factory.Create(connectionString, announcer, options);
var runner = new MigrationRunner(assembly, migrationContext, processor);
runner.MigrateUp(true);

Resources