स्थानीय विकास को तोड़ने के बिना EF कोर में Azure SQL सर्वर संस्करण निर्दिष्ट करें


10

एंटिटी फ्रेमवर्क कोर ने एज़ुरे SQL सर्वर के संस्करण को बदलने के लिए तरीके HasServiceTier और HasPerformanceLevel पेश किए । आप उन्हें इस तरह OnModelCreating में उपयोग कर सकते हैं :

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.HasServiceTier("Basic");
    modelBuilder.HasPerformanceLevel("Basic");
}

यदि आप ऐड-माइग्रेशन ऐड-माइग्रेशन का उपयोग करते हैं तो आपको इस तरह से माइग्रेशन मिलता है:

public partial class ChangedDatabaseServiceTierToBasic : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AlterDatabase()
            .Annotation("SqlServer:EditionOptions", "EDITION = 'Basic', SERVICE_OBJECTIVE = 'Basic'");
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AlterDatabase()
            .OldAnnotation("SqlServer:EditionOptions", "EDITION = 'Basic', SERVICE_OBJECTIVE = 'Basic'");
    }
}

यह ठीक काम करने लगता है, लेकिन जब मैं इस माइग्रेशन को स्थानीय गैर-Azure DB में विकास के उद्देश्यों के लिए लागू करने का प्रयास करता हूं तो मुझे निम्नलिखित त्रुटि मिलती है:

Microsoft.EntityFrameworkCore.Migrations[20402]
      Applying migration '20200413102908_ChangedDatabaseServiceTierToBasic'.
Applying migration '20200413102908_ChangedDatabaseServiceTierToBasic'.
fail: Microsoft.EntityFrameworkCore.Database.Command[20102]
      Failed executing DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      BEGIN
      DECLARE @db_name NVARCHAR(MAX) = DB_NAME();
      EXEC(N'ALTER DATABASE ' + @db_name + ' MODIFY ( 
      EDITION = ''Basic'', SERVICE_OBJECTIVE = ''Basic'' );');
      END
Failed executing DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
BEGIN
DECLARE @db_name NVARCHAR(MAX) = DB_NAME();
EXEC(N'ALTER DATABASE ' + @db_name + ' MODIFY ( 
EDITION = ''Basic'', SERVICE_OBJECTIVE = ''Basic'' );');
END
Microsoft.Data.SqlClient.SqlException (0x80131904): Incorrect syntax near '.'.
   at Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at Microsoft.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean isAsync, Int32 timeout, Boolean asyncWrite)
   at Microsoft.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, Boolean sendToPipe, Int32 timeout, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry, String methodName)
   at Microsoft.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteNonQuery(RelationalCommandParameterObject parameterObject)
   at Microsoft.EntityFrameworkCore.Migrations.MigrationCommand.ExecuteNonQuery(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.ExecuteNonQuery(IEnumerable`1 migrationCommands, IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabaseImpl(String targetMigration, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
ClientConnectionId:d9f92b81-9916-48ee-9686-6d0f567ab86f
Error Number:102,State:1,Class:15
Incorrect syntax near '.'.

मुझे लगता है कि आदेश गैर-Azure DBs के लिए मान्य नहीं हैं। तो सवाल यह है कि मैं गैर-एज़्योर डीबी पर निष्पादित होने वाली इन आज्ञाओं को कैसे रोक सकता हूं?


आपके माइग्रेशन कैसे चलते हैं? यदि कोड में, आप ASPNETCORE_ENVIRONMENT docs.microsoft.com/en-us/aspnet/core/fundamentals/…
पैट्रिक गूड

@PatrickGoode जो मुझे केवल स्थानीय db के लिए माइग्रेशन को पूरी तरह से अक्षम करने की अनुमति देगा, है ना? मैं चाहता हूं कि इस एक को छोड़कर सभी पलायन हों। एक समाधान यह होगा कि प्रवास की सामग्री को एक विन्यास-चर पर निर्भर किया जाए। मैं बस सोचता था कि क्या अधिक सुरुचिपूर्ण समाधान है।
टिम पोहलमैन

1
इनामों को बर्बाद करने के बजाय, आपको वास्तव में इसे EF कोर इश्यू ट्रैकर पर पोस्ट करना चाहिए क्योंकि यह उनका बग / मुद्दा - स्रोत है । जैसा कि आप देख सकते हैं, अन्य चीजों के लिए सशर्त ब्लॉक हैं, लेकिन इसके लिए नहीं। बेशक आप उनकी कक्षा को कस्टम के साथ बदल सकते हैं, लेकिन आपको पूरी विधि को कॉपी / पेस्ट / संशोधित करना होगा।
इवान स्टोव

1
मैंने अभी देखा कि आपने पहले ही ऐसा कर लिया है - # 20682 । सौभाग्य।
इवान स्टोव

1
@IvanStoev स्रोत कोड में कुछ दिलचस्प अंतर्दृष्टि है। इसे खोदने के लिए धन्यवाद।
टिम पोहल्मन

जवाबों:


3

EF कोर टीम अब इस मुद्दे से अवगत है और इसे अपने बैकलॉग में जोड़ दिया है: https://github.com/dotnet/efcore/issues/20682

इस बीच आधिकारिक तौर पर अनुशंसित वर्कअराउंड इस तरह दिखता है:

migrationBuilder.Sql(@"IF SERVERPROPERTY('EngineEdition') = 5
EXEC(N'ALTER DATABASE [ThreeOne.SomeDbContext] MODIFY (EDITION = ''Basic'',  SERVICE_OBJECTIVE = ''Basic'' );');
");

मैंने इसे मौजूदा डेटाबेस नाम के बिना काम करने के लिए संशोधित किया:

migrationBuilder.Sql
(
@"declare @dbname varchar(100)
set @dbname=quotename(db_name())
IF SERVERPROPERTY('EngineEdition') = 5
EXEC(N'ALTER DATABASE '+@dbname+' MODIFY (EDITION = ''Basic'', SERVICE_OBJECTIVE = ''Basic'' );');"
);

0

जरूर EDITIONऔरSERVICE_OBJECTIVE गैर Azure SQL डेटाबेस के लिए समर्थित नहीं हैं।

आपको अपने आदेश केवल Azure डेटाबेस के लिए चलाने की आवश्यकता है। अन्य प्रकार के SQL सर्वर के लिए आपको अपने कोड के निष्पादन की आवश्यकता होती है।

मैं SQL सर्वर संस्करण का पता लगाने का सुझाव देता हूं आपका कोड चलाने से पहले ।

इस उद्देश्य के लिए आप एक्सटेंशन विधि जोड़ सकते हैं:

public static class DatabaseFacadeExtensions
{
    public static bool IsSqlAzure(this DatabaseFacade database)
    {
        var parameter = new SqlParameter("edition", SqlDbType.NVarChar)
        {
            Size = 128,
            Direction = ParameterDirection.Output
        };

        database.ExecuteSqlCommand("SELECT @edition = CAST(SERVERPROPERTY('Edition') AS NVARCHAR)", parameter);

        var edition = parameter.Value.ToString();

        return edition.Equals("SQL Azure", StringComparison.OrdinalIgnoreCase);
    }
}

और अपने OnModelCreatingतरीके के अंदर आप अगले कोड का उपयोग कर सकते हैं:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    if (Database.IsSqlAzure())
    {
        modelBuilder.HasServiceTier("Basic");
        modelBuilder.HasPerformanceLevel("Basic");
    }
}

मुझे संदेह है कि यह काम करने वाला है। कोड जो समस्याओं का कारण बनता है वह OnModelCreating में माइग्रेशन में स्थित है। मैंने माइग्रेशन में कुछ इस तरह का उपयोग करने पर विचार किया, लेकिन यह थोड़ा विस्की लगता है, यही वजह है कि मैंने इस प्रश्न को खोला।
टिम पोहलमैन

0

यह बहुत गलत लगता है लेकिन यह काम करता है:

public partial class ChangedDatabaseServiceTierToBasic : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        if (IsHostedInAzure())
        {
            migrationBuilder.AlterDatabase()
                .Annotation("SqlServer:EditionOptions", "EDITION = 'Basic', SERVICE_OBJECTIVE = 'Basic'");
        }
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        if (IsHostedInAzure())
        {
            migrationBuilder.AlterDatabase()
                .OldAnnotation("SqlServer:EditionOptions", "EDITION = 'Basic', SERVICE_OBJECTIVE = 'Basic'");
        }
    }

    private static bool IsHostedInAzure()
    {
        var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
        var config = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env}.json", optional: true, reloadOnChange: true)
            .Build();

        var isHostedInAzureConfig = config["DatabaseSettings:IsHostedInAzure"];
        var setEdition = bool.TryParse(isHostedInAzureConfig, out var isHostedInAzure) && isHostedInAzure;
        return setEdition;
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.