Change database options during EF migration - database

We have some POCO classes and migrations enabled for my dataaccess layer we have created a initial migration to - remark we use the CreateDatabaseIfNotExist db initialization.
But in the database I would like have a MessageBody field that uses SQL Filestream, because the limitation on EF for Filestream - we try to do it manually in the migration script.
There we execute the following sql command.
Sql("alter table [msg].[Message] add [MessageBody] varbinary(max) FILESTREAM not null");
But I have to set the filestream options
So I would like to execute the following command during / before the migration.
ALTER DATABASE CURRENT SET FILESTREAM ( NON_TRANSACTED_ACCESS = FULL)
But when adding this bedore the creation of the tables I get the error: ALTER DATABASE statement not allowed within multi-statement transaction.
What's the best way to adapt Database options when you want to create the database automatically? Is it possible to intercept the migration process to execute some sql before the process executes the acutal migrations?

To fix error that occured to you you only need to invoke Sql method with additional bool parameter set to true:
Sql("alter table [msg].[Message] add [MessageBody] varbinary(max) FILESTREAM not null", true);
This will cause that your query will be executed in separate transaction.

Related

SSDT/Visual Studio Database Project publishing DACPAC referenced DML table trigger SQL71501

I'm unable to publish SQL DML triggers inside of a VS Database/SSDT project. Everything else seems to publish updates/creations fine. However, my triggers aren't ever generated in the script. I can update/create stored procedures, table valued functions (TVFs), contracts, queues and services just fine using [dbo].[ElementName] references.
MSSQL Version: SQL Server 2014 RS2
i.e. these all work fine as their respective type (contract, service, stored procedure, etc.) and update/create based on the source/destination.
Contract:
CREATE CONTRACT [//Web/Queue/BasicContract]
(
[//Web/Queue/RequestMessage] SENT BY INITIATOR,
[//Web/Queue/ReplyMessage] SENT BY TARGET
)
Stored Procedure [$(SystemDb) is set as a SQLCMD variable]:
CREATE PROCEDURE [dbo].[z_Dist_Tans_Error]
AS
BEGIN
DECLARE #RecordCount INT
SELECT #RecordCount = COUNT(*) FROM [$(SystemDb)].dbo.bcerr
END;
However, I get a reference error with this trigger SQL code. Error is commented in-line:
CREATE TRIGGER [z_Trg_MatlAvailable_Delete]
ON [dbo].[Matlavailable] --SQL71501: Trigger: [dbo].[z_Trg_MatlAvailable_Delete] has an unresolved reference to object [dbo].[Matlavailable]
FOR DELETE
AS
BEGIN
END
I can add the SQLCMD variable into the trigger creation query. This fixes the compile errors. But, when publishing it doesn't seem to detect the trigger doesn't exist in the destination database so it's never created in the script.
CREATE TRIGGER [z_Trg_MatlAvailable_Delete]
ON [$(SystemDb)].[dbo].[Matlavailable] --Error Resolved but never published
FOR DELETE
AS
BEGIN
END
If I add the table's SQL definition inside of my project I can resolve those reference issues and it actually publishes the triggers. However, I'm attaching this DML trigger to our ERP system's database. I have no control over how that database's table will evolve over time and I don't want my projects "definition" of that table to override the existing one.
It seems like I can reference DACPAC tables fine in queries but not attaching triggers (and probably more). Is there some way to create triggers using [$(VariableName)].[Schema].[TableName] that publish with VS Database Projects or a way to reference DACPAC tables to create triggers using just [Schema].[TableName] ?

Apply filter and block predicate to a new table

I am working with a SQL Server database which has row-level security implemented. To access content for a certain user, I need to append this to the SQL query:
EXEC SP_SET_SESSION_CONTEXT #key=N'UserId', #value=1
This works fine for existing tables in the database. However I have to add a new table to the database and I'm unable to add the same security to my new table.
This is how an existing table properties looks like
This is how the new table properties looks like
This is the code I found on the Microsoft docs and implemented it.
CREATE SECURITY POLICY RLS.NewTable
ADD FILTER PREDICATE RLS.fn_securitypredicate(AppUserId)
ON dbo.NewTable,
ADD BLOCK PREDICATE RLS.fn_securitypredicate(AppUserId)
ON dbo.NewTable AFTER INSERT
WITH (STATE = ON);
Obviously I got an error:
Cannot find the object "RLS.fn_securitypredicate" or this object is not an inline table-valued function.
Now I don't know where to find the correct block/filter predicate to be used on the new table.
TL;DR: where in a SQL Server database are the RLS predicates listed and how do I access/view them using Microsoft SQL Server Management Studio?
Can you confirm that you have the predicate function (RLS.fn_securitypredicate) in your database?
It will appear in Sql Server MS under -> Programmability -> Functions -> Table-valued Functions:

Change Database Collation after migration?

I have an MVC5 project and I populated my tables to the database via Entity Framework 6 - Code First migration. When looking to the tables, I ses that some characters do not displayed correctly and the Database Collation is SQL_Latin1_General_CP1_CI_AS instead of French_CI_AS.
1) What should be made in order to set the Database Collation while creating database via Code First? I found the following method below, but not sure if it is the best option for this purpose?
public override void Up()
{
Sql("ALTER DATABASE [YourDB] COLLATE [YourCollation]", suppressTransaction: true);
[...Your DB Objects Creation codes here...]
}
On the other hand, when using this script, I encounter "ALTER DATABASE failed. The default collation of database 'DbName' cannot be set to French_CI_AS" error.
2) Is it possible to change the Database Collation (via Code First or SQL) after adding some data to the related tables?
Any help would be appreciated...
It should be possible to change the collation even after adding data. I guess your problem comes from the fact that you need to put the database in single-user mode while you are executing the collation change. The database must be locked to prevent other connections from using it. After you finish you restore the multi-user mode.
If this is your case you should be getting this error in addition to the one you show in your question:
The database could not be exclusively locked to perform the operation.
The migration code to fix it:
public override void Up()
{
Sql("ALTER DATABASE [YourDB] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;");
Sql("ALTER DATABASE [YourDB] COLLATE [YourCollation];");
Sql("ALTER DATABASE [YourDB] SET MULTI_USER;");
[...Your DB Objects Creation codes here...]
}
I think you should remove the supressTransaction parameter. You should probably run this operation in a single transaction, in case some step fails.

“exec sp_reset_connection" getting called after some specific alter db properties and causes script to fail

My scenario is that I am calling multiple "ALTER DATABASE SET " commands followed by some table,index etc. creation commands from a sql script via C# following way:-
How to execute an .SQL script file using c#
string sqlConnectionString = #"Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=ccwebgrity;Data Source=SURAJIT\SQLEXPRESS";
string script = File.ReadAllText(#"E:\Project Docs\MX462-PD\MX756_ModMappings1.sql");
SqlConnection conn = new SqlConnection(sqlConnectionString);
Server server = new Server(new ServerConnection(conn));
server.ConnectionContext.ExecuteNonQuery(script);
The ALTER DB commands are like
ALTER DATABASE [MyDB] SET ANSI_NULL_DEFAULT OFF
GO
ALTER DATABASE [MyDB] SET ANSI_NULLS OFF
GO
ALTER DATABASE [MyDB] SET TRUSTWORTHY OFF
GO
I have around 20 calls like this and after that calls to create tables, indexes, keys etc.
What I observe is that if I try to alter any of these following db properties
HONOR_BROKER_PRIORITY
TRUSTWORTHY
DB_CHAINING
Then I see "exec sp_reset_connection" getting called in SQL Profiler and then it skips remaining commands being sent from the script from C# code.
This behavior has made my procedure not working properly from C# code but works fine from SSMS.
Can someone please explain this behavior of sp_reset_connection getting called after these specific db properties because in future I need to know what such properties can break code from C# while working in SSMS ?
There are few questions on SO regarding sp_reset_connection but those are about why they are called or enabling/disabling it etc. I couldn't find any relation of this SP to these three properties.

sqlpackage breaks when trying to alter a FILESTREAM column

I have a SQL Database project, where I have recently amended a FILESTREAM column to allow nulls. I am trying to publish the project's dacpac to a db where the column already exists, as a filestream column, but is currently NOT NULL.
I am performing the publish using the sqlpackage.exe command line tool (version 12.0.2882.1). However, it produces the error:
Error SQL72014: .Net SqlClient Data Provider: Msg 4990, Level 16, State 1, Line 1 Cannot alter column 'document' in table 'Document' to add or remove the FILESTREAM column attribute.
Error SQL72045: Script execution error. The executed script:
ALTER TABLE [dbo].[Document] ALTER COLUMN [document] VARBINARY (MAX) NULL;
The sql in the error looks like the generated script is trying to remove the FILESTREAM attribute on the column, which I guess is why SQL Server is complaining... but why is it doing this? My DB project still has the column marked as FILESTREAM
Fixed by upgrading sqlpackage.exe and associated libraries from version 12.0.2882.1 to 12.0.3021.1

Resources