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

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.

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"));

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

Sql Server Schemas, one private area per person, but have read access to others

I have a requirement for a database that is effectively a "play" area for people creating stats data for themselves and shared with others.
I have a read only database full of core data. All users have read access.
I want a second "play" database where 'n' people can query the "core" database and create there own tables, Sp's etc. I want these users to have a schema each. I want everything they create to be added to their schema by default unless they specify it explicitly (ie [dbo]) in the script. I want them all to be able to collaborate and be able to read data (and look at sp's) from other users schema but not add objects or execute sps' in the others users schema.
These users use 2014 management studio to run these queries. They all authenticate using Integrated Security (windows).
Can this be done?
I tried setting default schema on a user but by default when they add a table it goes to [dbo] because the property grid in 2014MS defaults to [dbo] and you have to edit it. If they just enter "create table Table1" I want it to go into their schema
I tried making the user the owner of the schema. I tried setting public to have select access to these user schemas. But something is not right!
I would have thought this was a common setup where developers get their own schema within a single database. Or, is it always the case that separate DB's are used to achieve this? I am sure others would appreciate a short script that sets this up for a couple of users :)
SQL Server admin is not my main area, so any guidance would be appreciated
For a test user User1, you can create a schema UserSchema1 and do the following
I want a second "play" database where 'n' people can query the "core" database
you can make the user part of the db_datareader role like this
USE [CoreDatabase]
GO
exec sp_addrolemember db_datareader, 'User1'
I want everything they create to be added to their schema by default
Create the schema and add appropriate permissions
USE [PlayDatabase]
GO
CREATE SCHEMA [UserSchema1] AUTHORIZATION dbo;
GO
GRANT ALTER, DELETE, EXECUTE, INSERT, REFERENCES, SELECT, UPDATE, VIEW DEFINITION ON SCHEMA::UserSchema1 TO User1;
GRANT CREATE TABLE, CREATE PROCEDURE, CREATE FUNCTION, CREATE VIEW TO User1;
Make the schema default for the user
ALTER USER [User1] WITH DEFAULT_SCHEMA=[UserSchema1]
For more info refer this thread
https://dba.stackexchange.com/questions/21733/allow-user-to-do-anything-within-his-own-schema-but-not-create-or-drop-the-schem
I want them all to be able to collaborate and be able to read data (and look at sp's) from other users schema but not add objects or execute sps' in the others users schema.
Allow user to view definition of other user's objects and do SELECT's on play database
USE [PlayDatabase]
GO
GRANT VIEW Definition TO [User1]
GO
exec sp_addrolemember db_datareader, 'User1'

how to make Simple Membership create tables with default dbo schema

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?

Resources