Search code examples
sql-serverdatabase-schemasqlclruser-defined-types

Set schema name in SqlUserDefinedTypeAttribute


When creating a UserDefinedType in C# code for the sake of SQLCLR integration, it is required that you prefix a class or struct with a SqlUserDefinedType, such as here:

[SqlUserDefinedType(
    Name = "g.Options",
    // ...
)]
public struct Options : INullable {
    // ...
}

Notice that in the "Name" parameter, I attempt to set a schema in addition to the object name. But, when I generate the script in the publish stage of a Visual Studio Database Project, I get:

CREATE TYPE [dbo].[g.Options]

There is no "schema" parameter for SqlUserDefinedType.

I do believe I can write the T-SQL script to make the type from the assembly specifically, but I would like to avoid that, as I plan on putting most of my types in different schemas and wouldn't be happy to have to register via explicit TSQL on each one.


EDIT:

As Solomon Rutzky points out, you can set the Default Schema in the project properties. It is certainly no substitute for something akin to a 'schema' parameter in SqlUserDefinedType, particularly if you want to work with multiple schemas, but it certainly gets the job done for many people's needs.

A post-deployment script will technically get the job done, but unfortunately, the comparison engine doesn't know about the post-deployment logic and so will perpetually register the schema difference as something that needs to be changed. So all your affected objects will be dropped and re-created on every publish regardless of whether you changed them or not.


Solution

  • The Schema name is specified in a singular location per each project, not per object.

    You can set it in Visual Studio via:

    "Project" (menu) -> "{project_name} Properties..." (menu option) -> "Project Settings" (tab)

    On the right side, in the "General" section, there is a text field for "Default schema:"

    OR:

    you can manually edit your {project_name}.sqlproj file, and in one of the top <PropertyGroup> elements (one that does not have a "Condition" attribute; the first such element is typically used), you can create (or update if it already exists) the following element:

    <DefaultSchema>dbo</DefaultSchema>
    

    HOWEVER, if you are wanting to set one object (such as a UDT) to a different Schema name than the rest of the objects are using, that would have to be done manually in a Post Release SQL script. You can add a SQL script to your project, then in the Solution Explorer on the right side, select the SQL script, go to its Properties, and for "BuildAction", select "PostDeploy". In that post-deploy script, issue an ALTER SCHEMA statement:

    ALTER SCHEMA [g] TRANSFER TYPE::dbo.Options;