-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Default Sql Server db functions to DBO schema #9303
Conversation
{ | ||
var dbFunctionBuilder = new InternalDbFunctionBuilder(dbFunction); | ||
|
||
dbFunctionBuilder.HasSchema("dbo", ConfigurationSource.Convention); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this default to "dbo" always or whatever is defined on model?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not understanding your question. With this change if you don't set a schema it will default to dbo.
One thing I just thought of is if we should use the global schema if it is set or go with this default.
@anpete thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One thing I just thought of is if we should use the global schema if it is set or go with this default.
That's what I meant. If user has done
modelBuilder.HasDefaultSchema("MySchema");
Then should function go there?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should it be IModelBuiltConvention
?
So that once the model is fully built, plug in missing schemas in DbFunction based on default if set on model or "dbo"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would there every be a reason someone would try to pull the schema back out of a function before finishing building the entire model? That is the only thing I can think of where waiting for IModelBuiltConvention
would be different.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suppose user defines a function without configuring schemas & then define the default schema.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea that would be worse. Ok ill refactor it tonight.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I switched it over to IModelBuiltConvention
I need to pop a few unit tests to deal with the defaultSchema vs defaulting to dbo still.
1e29900
to
2e00bb2
Compare
Updated and unit tests added. |
Can you add a functional test when default schema is specified which is different from dbo and function is defined on that schema and query picks up the schema from model correctly. |
Let me make sure I am following what you are asking for. You want the default schema set to "abc" and the function set to "xyz" and then make sure the sql uses "xyz"? By functional test do you want it to actually hit a database and run a query? |
Since the convention does not do anything if model has DefaultSchema set, |
I believe current functional tests covers when function is defined without schema and we use the "dbo" |
If there is no schema set on the function but a default schema is set then the default schema is used. If you don't want the default schema to be used at all then you need to set the schema on the function to an empty string. For Sql Server that use case would only be for calling built in functions, all udf calls require a schema. The logic order currently is
Any function test that hit the db need to be in |
That's the scenario I want tested because I have doubts on that. We added For all local dev machines & CI machines which are not dropping database, this causes mismatch since there will be outdated northwind in sqlserver. And that leads to failure unless northwind database is manually dropped. |
|
||
namespace Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal | ||
{ | ||
public class SqlServerDbFunctionConvention : IModelBuiltConvention |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AndriySvyryd - Name sounds good to you?
I don't see a Do you not want me to modify the northwind.sql and find a different approach for creating a new databsae and creating the function for each run? |
Ah, its |
I actually have a big family wedding the rest of this week/weekend so I won't be able to get these changes in until early next week. |
@pmiddleton - No rush, we have a lot of time before next release 😄 |
@smitpatel - I added the unit tests you were looking for. Let me know what you think. |
@pmiddleton - Thanks I was looking for precisely that test since I was not able to understand how the default model schema was set on function. After looking more in code today I found out the Should What do you think? |
It depends if we want the user to be able to read the name and schema, set via the attribute, during OnModelCreating. As it stands now you can, if we switch to a ModelBuiltConvention you won't be able to. That would also be a minor change to end user behavior from 2.0 to 2.1. |
The test in QueryBugsTest fail if function is defined using Attribute without specifying schema. The Further, if user set default schema then define function then set default schema to something else then we are not updating the schema in db function. This is because |
Though above is in existing code and out of the scope of PR. |
filed #9360 |
Rebased. |
Based on your findings I'm leaning towards just applying all of the defaults in a ModelBuiltConvention. We can make Thoughts? |
@AndriySvyryd needs to approve it. |
public virtual string Schema | ||
{ | ||
get => _schema; | ||
get => _schema ?? new RelationalModelAnnotations(_model).DefaultSchema ?? DefaultSchema; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would this be same as _model.Relational().DefaultSchema
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes - I will switch it to add the abstraction back in.
Check.NotNull(modelBuilder, nameof(modelBuilder)); | ||
Check.NotNull(name, nameof(name)); | ||
|
||
if (name.StartsWith(RelationalAnnotationNames.DbFunction, StringComparison.OrdinalIgnoreCase) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use StringComparison.Ordinal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also in RelationalDbFunctionConvention
.
Actually you can derive this from RelationalDbFunctionConvention
and replace it in SqlServerConventionSetBuilder
c4aa055
to
9c04bb6
Compare
@AndriySvyryd - Changes made |
Check.NotNull(modelBuilder, nameof(modelBuilder)); | ||
Check.NotNull(name, nameof(name)); | ||
|
||
base.Apply(modelBuilder, name, annotation, oldAnnotation); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling base this way means the check is happening twice. Instead a helper function to do the task of setting name/schema which can be overridden in derived convention could be more DRY.
@smitpatel - switched to a helper method. |
Merged via 7529563 Thanks for contribution @pmiddleton |
Hey Paul et alia, reading the two issues on this, my understanding is that dbo is the conventional default schema. But (on EF Core 2.0.1) my queries using a function are failing (sql server returns function not found error) unless I explicitly set the schema to dbo in the function ala
Am I misunderstanding something? |
@julielerman - Yes, that would be expected behavior in 2.0.1. The issue is fixed in 2.1.0-preview1-final |
yeah .just found the note in #9663 :) |
@julielerman - Yup I missed that one in 2.0. |
@julielerman - 2.1.0-preview1-final will also allow you to use instance methods as well as static methods for db functions. See #9755 |
even with the current requirement for the schema specified, it's such a great feature. I had only read about it up until now but as I'm experimenting with it, I'm so impressed! :) |
Thanks! |
Function quoting logic was changed (for now): all function names are quoted just like any other identifier (the default EF Core behavior is only to quote schema-less functions). This meant changing all expression translators to generate lower-case names (lower() instead of LOWER()), and also to add a hardcoded list of functions which EF Core generates in upper-case but which shouldn't get quoted (e.g. SUM()). See: * dotnet/efcore#8507 * dotnet/efcore#12044 * dotnet/efcore#12757 * dotnet/efcore#9558 * dotnet/efcore#9303
Function quoting logic was changed (for now): all function names are quoted just like any other identifier (the default EF Core behavior is only to quote schema-less functions). This meant changing all expression translators to generate lower-case names (lower() instead of LOWER()), and also to add a hardcoded list of functions which EF Core generates in upper-case but which shouldn't get quoted (e.g. SUM()). See: * dotnet/efcore#8507 * dotnet/efcore#12044 * dotnet/efcore#12757 * dotnet/efcore#9558 * dotnet/efcore#9303
For now, only unquoted function names are supported (i.e. all lower- case, no special chars). Quoting logic for functions is quite complicated, see below issues for details. See: * dotnet/efcore#8507 * dotnet/efcore#12044 * dotnet/efcore#12757 * dotnet/efcore#9558 * dotnet/efcore#9303
For now, only unquoted function names are supported (i.e. all lower- case, no special chars). Quoting logic for functions is quite complicated, see below issues for details. See: * dotnet/efcore#8507 * dotnet/efcore#12044 * dotnet/efcore#12757 * dotnet/efcore#9558 * dotnet/efcore#9303
For now, only unquoted function names are supported (i.e. all lower- case, no special chars). Quoting logic for functions is quite complicated, see below issues for details. See: * dotnet/efcore#8507 * dotnet/efcore#12044 * dotnet/efcore#12757 * dotnet/efcore#9558 * dotnet/efcore#9303
Set the the default schema for db functions in Sql Server to dbo.
Addresses #9214