how to make Simple Membership create tables with default dbo schema - sql-server

I have an issue with Simple Membership with SQL server using Entity framework code first.
When I run
WebSecurity.InitializeDatabaseConnection( "MyDB", "Users",
"UserID", "Username", true);
on my own development pc, It creates the following tables
dbo.Users
dbo.webpages_Membership
dbo.webpages_Roles
dbo.webpages_UsersInRoles
But, when I run the site on a host it creates the tables as:
myusername.Users
myusername.webpages_Membership
myusername.webpages_Roles
myusername.webpages_UsersInRoles
Please,
how do I get the simple membership provider to create the tables with the default dbo schema?

You can find here a good way to do this without specify a default schema for your user.
You just need to follow this implementation and define the default schema.
Like this:
[Table("webpages_Membership", Schema = "SCHEMA_NAME")]

WebSecurity.InitializeDatabaseConnection uses the default schema
assigned to your Database User to create\access the tables
for the SimpleMembershipProvider.
So you need to change the default schema your user has on the Database on your host.
Does your host allow you to set the default schema for your Database User?

Related

Objects being created as DBO for all users in SQL Server application

We have Windows Authentication on our SQL Server Databases.
Every object gets created as dbo which I don't mind. But we are unable to track who created what? Can someone help on how it can be managed so we can at least track who is doing what? The login names from the trace is also generic
login name - ABC\gMSA_SQL$
If I login to the server with my windows authentication and run the below command select SUSER_NAME(), I can see my username and not a generic one. So now if I create a table where can I get this username from?
The default schema of the user are set to dbo. It could be due to many reasons, as mentioned in the below msdn reference
The default schema will be the first schema that will be searched by
the server when it resolves the names of objects for this database
user. Unless otherwise specified, the default schema will be the owner
of objects created by this database user.
If the user has a default schema, that default schema will used. If
the user does not have a default schema, but the user is a member of a
group that has a default schema, the default schema of the group will
be used. If the user does not have a default schema, and is a member
of more than one group, the default schema for the user will be that
of the Windows group with the lowest principal_id and an explicitly
set default schema. (It is not possible to explicitly select one of
the available default schemas as the preferred schema.) If no default
schema can be determined for a user, the dbo schema will be used.
DEFAULT_SCHEMA can be set before the schema that it points to is
created.
DEFAULT_SCHEMA cannot be specified when you are creating a user mapped
to a certificate, or an asymmetric key.
The value of DEFAULT_SCHEMA is ignored if the user is a member of the
sysadmin fixed server role. All members of the sysadmin fixed server
role have a default schema of dbo.
You can find out the default schema of the users by running the below query. Refer to sys.database_principals
SELECT default_schema_name FROM sys.database_principals
If you want to restrict the users to only create objects on their schema, you have to do below things:
CREATE SCHEMA [userPrincipalSchema];
GO
CREATE USER [userPrincipal]
WITH PASSWORD='SUPERCOMPLEXPASSWORDHERE'
, DEFAULT_SCHEMA=[userPrincipalSchema]
GO
DENY ALTER ON SCHEMA::[dbo] to [userPrincipal]
GO
ALTER AUTHORIZATION ON SCHEMA::[userPrincipalSchema] to [userPrincipal];
GO
GRANT CREATE TABLE, CREATE VIEW, CREATE PROCEDURE TO [userPrincipal];
GO
This way, you can ensure that the [userPrincpal] is able to create objects only on their schema and you can track, the objects created by them.

Change EF Core Migrations to different default owner

I am creating a new .NET Core 3.1.3 application, connecting to a new SQL Server 2016 database. The connection is a trusted connection. The EF migration tool is creating the tables with me as the owner.
dotnet ef migrations add InitialDb
dotnet ef database update
I don't want that. I want the tables to be owned by a service id that we have created for the purpose. What is the safest and most efficient way to default table creation to that owner?
If you don't specify a schema for your Entities, EF will generate the DDL with no schema specified. And in SQL Server this means that the object will be created in the user's default schema. Normally the user's default schema should be dbo, but if it's not, then the object will be created in a different schema.
And in SQL Server objects are owned (again by default) by the owner of the schema in which they are created.
So, configure the tables to be created in the dbo schema, or configure your user's default schema to be dbo, and the objects will be created in the dbo schema and owned by dbo.
eg in OnModelCreating, add
foreach (var et in modelBuilder.Model.GetEntityTypes())
{
et.SetSchema("dbo");
}
or in SQL
alter user [yourdomain\youruser] with default_schema=dbo
Note that if you are the database owner, or a sysadmin, you always connect to the database as dbo, and your unqualified DDL will create objects in the dbo schema.
I want the tables to be owned by a service id
You don't normally want objects owned by the identity that the application uses to connect, as that identity should be in a role with least-privileges. EG no ability to drop tables or create triggers. Typically the objects should simply be owned by dbo.
At least as of EF Core 6 you can be more succinct with
modelBuilder.HasDefaultSchema("dbo");
Note that if you are using the built-in history table you will need to place extra code in the onConfiguring. Something like
optionsBuilder.UseSqlServer(x => x.MigrationsHistoryTable("__EFMigrationsHistory", "dbo"));

.NET Code First is adding user login as default table schema

I am having a strange behavior when I apply a migration to my online db with Entity Framework Core. All of the tables take by default the UserId defined in my connectionstring as the default schema. I know how to change it but I'd like to understand the reason why this is happening. Notice that it does not happen with a local database, the schema remains as "dbo".
You can set the default schema for the User using:
ALTER USER myUser WITH DEFAULT_SCHEMA [myschema]
So you can set your user to have the default schema of dbo, if you wish.
I'm guessing dbo is already set as the default schema for the user that you connect with locally.
You can also specify the default schema in Entity Framework Core. See this question: Where is HasDefaultSchema in Entity Framework Core?
Note that it is a good practice to use a different user for applying your migrations than what you use for querying etc.

Set dbo as default schema for all new tables

I have a database installed on four different production servers. Each server has its own different user. When I create a new table using create statement on these servers every server sets / prepends their user name e.g.
Create Table tab_1 ... will be created as
abc.tab_1 on server_1 using abc as login
def.tab_1 on server_2 using def as login
ghi.tab_1 on server_3 using ghi as login
jkl.tab_1 on server_4 using jkl as login
I want to use dbo as default schema and have to use following statement on every server for every new table
ALTER SCHEMA dbo TRANSFER login.table_name;
Is there any way to modify Create Table statement or other setting by which every table is created on all servers as dbo.table_name
I am using shared hosting and there are many restrictions in SSMS, so a query based solution would be appropriate.
You have control over the create table queries? In that case simply specify dbo in create:
CREATE TABLE dbo.dummy ();
For changing default schema for a user see this answer: https://stackoverflow.com/a/8208124/3480246

Why is it not possible to change the default schema to user schema for the Windows Login

In this picture, you can see if I login using windows authentication, the default user and schema are dbo.
I have a database called trunk2 and its default user is trunk2 and default schema is trunk2.
If I login as "trunk2", I can access the schema a"trunk2" as the default schema
But if I login using the windows authentication, I am not able to populate the schema "trunk2" as the default schema for the database trunk2
It is populating the schema "dbo" as the default schema. Why ?
How can I login using the Windows login and access the schema "trunk2" as the default schema of the database "trunk2"?
Please see in the below picture, for the login "trunk2", I have no problem in accessing the default schema "trunk2" for database "trunk2" and default user "trunk2"
you cannot assign a default schema in SQL Server to a Windows-authenticated set of users.
Why? it is by design.
Look at the following link:
http://support.microsoft.com/en-us/kb/918346
this is sort of Microsoft BS... given the fact that we have restored a database with a set of tables associated to "dbo" and creating some stored procedures in our client applicatoin (after using a "trusted connection") puts them into domain\username schema, not into dbo although it'S group entry in SQL management studio has clearly being associated "dbo" as default schema.
Thereby executing the stored precedures after their creation gets me an ugly error "the stored procedure is in different schema than the table" and an empty resultset. However the error level reported by the SQL server is not high enough to create an exception that could be catched in an try/error code sequence.... and when it's not an error then data is missing in the client app. Very ugly, very ugly.
A workaround was to fix the schema membership of the freshly created stored procedures with "alter schema dbo transfer [domain\username].[sp name]" but with houndreds of windows users that gets me an administrative nightmare.... and this is still in SQL Server 2014

Resources