Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
BIR SQL projesi dağıtırken özel eylemler gerçekleştirmek için dağıtım katkıda bulunanları oluşturabilirsiniz. DeploymentPlanModifier veya DeploymentPlanExecutor'den birini oluşturabilirsiniz. Planı yürütülmeden önce değiştirmek için DeploymentPlanModifier ve plan yürütülürken işlemleri gerçekleştirmek için DeploymentPlanExecutor kullanın. Bu kılavuzda SqlRestartableScriptContributor adlı bir DeploymentPlanModifier oluşturacaksınız. DeploymentPlanModifier SqlRestartableScriptContributor, dağıtım betiğindeki işlem gruplarına yürütme sırasında bir hata oluşursa tamamlanana kadar betiğin yeniden çalıştırılmasını sağlamak için IF deyimleri ekler.
Bu kılavuzda aşağıdaki önemli görevleri yerine getirebilirsiniz:
Önkoşullar
Bu kılavuzu tamamlamak için aşağıdaki bileşenlere ihtiyacınız vardır:
Visual Studio'nun SQL Server Veri Araçları'nı içeren ve C# geliştirmeyi destekleyen bir sürümünü yüklemiş olmanız gerekir.
SQL nesneleri içeren bir SQL projeniz olmalıdır.
Veritabanı projesini dağıtabileceğiniz bir SQL Server örneği.
Not
Bu kılavuz, SQL Server Veri Araçları'nın SQL özelliklerini zaten bilen kullanıcılara yöneliktir. Sınıf kitaplığı oluşturma ve sınıfa kod eklemek için kod düzenleyicisini kullanma gibi temel Visual Studio kavramları hakkında bilgi sahibi olmanız da beklenir.
Dağıtım Katkıcısı Oluştur
Dağıtım katkı sağlayıcısı oluşturmak için aşağıdaki görevleri gerçekleştirmeniz gerekir:
Bir sınıf kitaplığı projesi oluşturun ve gerekli referansları ekleyin.
DeploymentPlanModifiersınıfından devralan SqlRestartableScriptContributor adında bir sınıf tanımlayın.
OnExecute yöntemini geçersiz kılın.
Özel yardımcı yöntemleri ekleyin.
Sonuçta elde edilen derlemeyi oluşturun.
Sınıf kitaplığı projesi oluşturmak için
MyOtherDeploymentContributor adlı bir C# sınıf kitaplığı (.NET Framework) projesi oluşturun.
"Class1.cs" dosyasını "SqlRestartableScriptContributor.cs" olarak yeniden adlandırın.
Çözüm Gezgini'nde proje düğümüne sağ tıklayın ve Başvuru Ekleöğesine tıklayın.
Çerçeveler sekmesinde System.ComponentModel.Composition seçin.
Project menüsünden NuGet paketlerini yönet seçeneğini seçin. Microsoft.SqlServer.DacFxiçin en son kararlı sürümleri yükleyin.
Ardından sınıfa kod eklemeye başlayın.
SqlRestartableScriptContributor sınıfını tanımlamak için
Kod düzenleyicisinde, class1.cs dosyasını aşağıdaki ile eşleşen deyimlerini kullanacak şekilde güncelleyin.
using System; using System.Collections.Generic; using System.Globalization; using System.Text; using Microsoft.SqlServer.Dac.Deployment; using Microsoft.SqlServer.Dac.Model; using Microsoft.SqlServer.TransactSql.ScriptDom;
Sınıf tanımını aşağıdaki örnekle eşleşecek şekilde güncelleştirin:
/// <summary> /// This deployment contributor modifies a deployment plan by adding if statements /// to the existing batches in order to make a deployment script able to be rerun to completion /// if an error is encountered during execution /// </summary> [ExportDeploymentPlanModifier("MyOtherDeploymentContributor.RestartableScriptContributor", "1.0.0.0")] public class SqlRestartableScriptContributor : DeploymentPlanModifier { }
Şimdi dağıtım planı değiştiricisi DeploymentPlanModifier'i devralan katkı sağlayanınızı tanımlamış oldunuz. Derleme ve dağıtım işlemleri sırasında, özel katkıda bulunanlar standart bir uzantı dizininden yüklenir. Dağıtım planını değiştiren katkıda bulunanlar, ExportDeploymentPlanModifier özniteliğiyle tanımlanır. Katkıda bulunanların bulunabilmesi için bu öznitelik gereklidir. Bu öznitelik aşağıdaki işlev dekoratörüne benzer görünmelidir:
[ExportDeploymentPlanModifier("MyOtherDeploymentContributor.RestartableScriptContributor", "1.0.0.0")]
Aşağıdaki üye bildirimlerini ekleyin:
private const string BatchIdColumnName = "BatchId"; private const string DescriptionColumnName = "Description"; private const string CompletedBatchesVariableName = "CompletedBatches"; private const string CompletedBatchesVariable = "$(CompletedBatches)"; private const string CompletedBatchesSqlCmd = @":setvar " + CompletedBatchesVariableName + " __completedBatches_{0}_{1}"; private const string TotalBatchCountSqlCmd = @":setvar TotalBatchCount {0}"; private const string CreateCompletedBatchesTable = @" if OBJECT_ID(N'tempdb.dbo." + CompletedBatchesVariable + @"', N'U') is null begin use tempdb create table [dbo].[$(CompletedBatches)] ( BatchId int primary key, Description nvarchar(300) ) use [$(DatabaseName)] end ";
Ardından, veritabanı projesi dağıtıldığında çalıştırmak istediğiniz kodu eklemek için OnExecute yöntemini geçersiz kılacaksınız.
OnExecute'ı geçersiz kılmak için
SqlRestartableScriptContributor sınıfınıza aşağıdaki yöntemi ekleyin:
/// <summary> /// You override the OnExecute method to do the real work of the contributor. /// </summary> /// <param name="context"></param> protected override void OnExecute(DeploymentPlanContributorContext context) { // Replace this with the method body }
OnExecute yöntemini DeploymentPlanContributortemel sınıfından geçersiz kılarsınız. DeploymentPlanContributor, DeploymentPlanModifier ve DeploymentPlanExecutoriçin temel sınıftır. DeploymentPlanContributorContext nesnesi, Belirtilen bağımsız değişkenlere, hedefin kaynak ve veritabanı modeline, dağıtım planına ve dağıtım seçeneklerine erişim sağlayan OnExecute yöntemine geçirilir. Bu örnekte dağıtım planını ve hedef veritabanı adını alacağız.
Şimdi OnExecute yöntemine bir gövdenin başlangıcını ekleyin:
// Obtain the first step in the Plan from the provided context DeploymentStep nextStep = context.PlanHandle.Head; int batchId = 0; BeginPreDeploymentScriptStep beforePreDeploy = null; // Loop through all steps in the deployment plan while (nextStep != null) { // Increment the step pointer, saving both the current and next steps DeploymentStep currentStep = nextStep; nextStep = currentStep.Next; // Add additional step processing here } // if we found steps that required processing, set up a temporary table to track the work that you are doing if (beforePreDeploy != null) { // Add additional post-processing here } // Cleanup and drop the table DeploymentScriptStep dropStep = new DeploymentScriptStep(DropCompletedBatchesTable); base.AddAfter(context.PlanHandle, context.PlanHandle.Tail, dropStep);
Bu kodda birkaç yerel değişken tanımlayacak ve dağıtım planındaki tüm adımların işlenmesini işleyen döngü ayarlayacağız. Döngü tamamlandıktan sonra biraz işlem sonrası yapmamız gerekecek ve ardından plan yürütülürken ilerleme durumunu izlemek için dağıtım sırasında oluşturduğumuz geçici tabloyu bırakacağız. Burada anahtar türleri şunlardır: DeploymentStep ve DeploymentScriptStep. Önemli bir yöntem AddAfter'dir.
Şimdi "Buraya ek adım işleme ekleyin" yazan açıklamayı değiştirmek için ek adım işlemeyi ekleyin:
// Look for steps that mark the pre/post deployment scripts // These steps will always be in the deployment plan even if the // user's project does not have a pre/post deployment script if (currentStep is BeginPreDeploymentScriptStep) { // This step marks the beginning of the predeployment script. // Save the step and move on. beforePreDeploy = (BeginPreDeploymentScriptStep)currentStep; continue; } if (currentStep is BeginPostDeploymentScriptStep) { // This is the step that marks the beginning of the post deployment script. // We do not continue processing after this point. break; } if (currentStep is SqlPrintStep) { // We do not need to put if statements around these continue; } // if we have not yet found the beginning of the pre-deployment script steps, // skip to the next step. if (beforePreDeploy == null) { // We only surround the "main" statement block with conditional // statements continue; } // Determine if this is a step that we need to surround with a conditional statement DeploymentScriptDomStep domStep = currentStep as DeploymentScriptDomStep; if (domStep == null) { // This step is not a step that we know how to modify, // so skip to the next step. continue; } TSqlScript script = domStep.Script as TSqlScript; if (script == null) { // The script dom step does not have a script with batches - skip continue; } // Loop through all the batches in the script for this step. All the statements // in the batch will be enclosed in an if statement that will check the // table to ensure that the batch has not already been executed TSqlObject sqlObject; string stepDescription; GetStepInfo(domStep, out stepDescription, out sqlObject); int batchCount = script.Batches.Count; for (int batchIndex = 0; batchIndex < batchCount; batchIndex++) { // Add batch processing here }
Kod açıklamaları işlemeyi açıklar. Üst düzeyde, bu kod önemsediğiniz adımları arar, başkalarını atlar ve dağıtım sonrası adımların başına ulaştığınızda durdurulur. Eğer adım, koşullularla çevrilmesi gereken ifadeler içeriyorsa, ek işleme gerçekleştiririz. Anahtar türleri, yöntemleri ve özellikleri DacFx kitaplığındaki şu bileşenleri içerir: BeginPreDeploymentScriptStep, BeginPostDeploymentScriptStep, TSqlObject, TSqlScript, Script, DeploymentScriptDomStepve SqlPrintStep.
Şimdi "Toplu işlemeyi buraya ekleyin" ifadesinin yerine toplu işlem kodunu ekleyin:
// Create the if statement that will contain the batch's contents IfStatement ifBatchNotExecutedStatement = CreateIfNotExecutedStatement(batchId); BeginEndBlockStatement statementBlock = new BeginEndBlockStatement(); ifBatchNotExecutedStatement.ThenStatement = statementBlock; statementBlock.StatementList = new StatementList(); TSqlBatch batch = script.Batches[batchIndex]; int statementCount = batch.Statements.Count; // Loop through all statements in the batch, embedding those in an sp_execsql // statement that must be handled this way (schemas, stored procedures, // views, functions, and triggers). for (int statementIndex = 0; statementIndex < statementCount; statementIndex++) { // Add additional statement processing here } // Add an insert statement to track that all the statements in this // batch were executed. Turn on nocount to improve performance by // avoiding row inserted messages from the server string batchDescription = string.Format(CultureInfo.InvariantCulture, "{0} batch {1}", stepDescription, batchIndex); PredicateSetStatement noCountOff = new PredicateSetStatement(); noCountOff.IsOn = false; noCountOff.Options = SetOptions.NoCount; PredicateSetStatement noCountOn = new PredicateSetStatement(); noCountOn.IsOn = true; noCountOn.Options = SetOptions.NoCount; InsertStatement batchCompleteInsert = CreateBatchCompleteInsert(batchId, batchDescription); statementBlock.StatementList.Statements.Add(noCountOn); statementBlock.StatementList.Statements.Add(batchCompleteInsert); statementBlock.StatementList.Statements.Add(noCountOff); // Remove all the statements from the batch (they are now in the if block) and add the if statement // as the sole statement in the batch batch.Statements.Clear(); batch.Statements.Add(ifBatchNotExecutedStatement); // Next batch batchId++;
Bu kod, BEGIN/END bloğuyla birlikte bir IF deyimi oluşturur. Daha sonra yığın içindeki ifadeler üzerinde ek işlem gerçekleştiririz. Bu işlem tamamlandıktan sonra, betik yürütmenin ilerleme durumunu izleyen geçici tabloya bilgi eklemek için bir INSERT deyimi kullanırız. Son olarak, toplu işlemi güncelleştirin ve daha önce orada olan deyimleri içinde bu deyimleri içeren yeni EĞER ile değiştirin. Anahtar türleri, yöntemleri ve özellikleri şunlardır: IfStatement, BeginEndBlockStatement, StatementList, TSqlBatch, PredicateSetStatement, SetOptionsve InsertStatement.
Şimdi deyimi işleme döngüsünün gövdesini ekleyin. "Buraya ek ifade işleme ekleyin' ifadesinin bulunduğu yorumu değiştirin."
TSqlStatement smnt = batch.Statements[statementIndex]; if (IsStatementEscaped(sqlObject)) { // "escape" this statement by embedding it in a sp_executesql statement string statementScript; domStep.ScriptGenerator.GenerateScript(smnt, out statementScript); ExecuteStatement spExecuteSql = CreateExecuteSql(statementScript); smnt = spExecuteSql; } statementBlock.StatementList.Statements.Add(smnt);
Toplu iş içindeki her ifade için, ifade sp_executesql ifadesiyle sarmalanması gereken bir türdeyse, ifadesini buna göre değiştirin. Kod daha sonra oluşturduğunuz BEGIN/END bloğu için deyimini deyim listesine ekler. Anahtar türleri, yöntemleri ve özellikleri TSqlStatement ve ExecuteStatementiçerir.
Son olarak, "Buraya ek son işlem ekleyin" yazan açıklamanın yerine son işlem bölümünü ekleyin:
// Declare a SqlCmd variables. // // CompletedBatches variable - defines the name of the table in tempdb that will track // all the completed batches. The temporary table's name has the target database name and // a guid embedded in it so that: // * Multiple deployment scripts targeting different DBs on the same server // * Failed deployments with old tables do not conflict with more recent deployments // // TotalBatchCount variable - the total number of batches surrounded by if statements. Using this // variable pre/post deployment scripts can also use the CompletedBatches table to make their // script rerunnable if there is an error during execution StringBuilder sqlcmdVars = new StringBuilder(); sqlcmdVars.AppendFormat(CultureInfo.InvariantCulture, CompletedBatchesSqlCmd, context.Options.TargetDatabaseName, Guid.NewGuid().ToString("D")); sqlcmdVars.AppendLine(); sqlcmdVars.AppendFormat(CultureInfo.InvariantCulture, TotalBatchCountSqlCmd, batchId); DeploymentScriptStep completedBatchesSetVarStep = new DeploymentScriptStep(sqlcmdVars.ToString()); base.AddBefore(context.PlanHandle, beforePreDeploy, completedBatchesSetVarStep); // Create the temporary table we will use to track the work that we are doing DeploymentScriptStep createStatusTableStep = new DeploymentScriptStep(CreateCompletedBatchesTable); base.AddBefore(context.PlanHandle, beforePreDeploy, createStatusTableStep);
İşlemlerimiz, şartlı bir ifadeyle sardığımız bir veya birden fazla adım bulunduyda, SQLCMD değişkenlerini tanımlamak amacıyla dağıtım betiğine ifadeler eklemeliyiz. Değişkenler şunlardır:
- CompletedBatches, dağıtım betiğinin betik yürütülürken hangi toplu işlemlerin başarıyla tamamlandığını izlemek için kullandığı geçici tablo için benzersiz bir ad içerir
- TotalBatchCount dağıtım betiğindeki toplam toplu iş sayısını içerir
İlgi çekici diğer türler, özellikler ve yöntemler şunlardır:
StringBuilder, DeploymentScriptStepve AddBefore.
Ardından, bu yöntem tarafından çağrılan yardımcı yöntemleri tanımlarsınız.
Yardımcı yöntemleri eklemek için
Bir dizi yardımcı yöntem tanımlanmalıdır. Önemli yöntemler şunlardır:
Yöntemi Açıklama SQLOluşturVeÇalıştır Sağlanan bir ifadeyi EXEC sp_executesql ifadesi ile sarmak için CreateExecuteSQL metodunu tanımlayın. Anahtar türleri, yöntemleri ve özellikleri şu DacFx API bileşenlerini içerir: ExecuteStatement, ExecutableProcedureReference, SchemaObjectName, ProcedureReferenceve ExecuteParameter. CreateCompletedBatchesName CreateCompletedBatchesName yöntemini tanımlayın. Bu yöntem, bir toplu iş için geçici tabloya eklenen adı oluşturur. Anahtar türleri, yöntemleri ve özellikleri şu DacFx API bileşenlerini içerir: SchemaObjectName. IsStatementEscaped IsStatementEscaped yöntemini tanımlayın. Bu yöntem, model öğesi türünün bir IF deyimi içine alınabilmesi için deyimin bir EXEC sp_executesql deyiminde sarılmasını gerektirip gerektirmediğini belirler. Anahtar türleri, yöntemleri ve özellikleri şu DacFx API bileşenlerini içerir: TSqlObject.ObjectType, ModelTypeClass ve aşağıdaki model türleri için TypeClass özelliği: Schema, Procedure, View, TableValuedFunction, ScalarFunction, DatabaseDdlTrigger, DmlTrigger, ServerDdlTrigger. YığınTamamlaEkleOluştur CreateBatchCompleteInsert yöntemini tanımlayın. Bu yöntem, betik yürütmenin ilerleme durumunu izlemek için dağıtım betiğine eklenen INSERT deyimini oluşturur. Anahtar türleri, yöntemleri ve özellikleri şu DacFx API bileşenlerini içerir: InsertStatement, NamedTableReference, ColumnReferenceExpression, ValuesInsertSource ve RowValue. ÇalıştırılmadıysaOluşturIfadesi CreateIfNotExecutedStatement yöntemini tanımlayın. Bu yöntem, geçici toplu işlemlerin yürütülür tablosunun bu toplu işlemin zaten yürütülmüş olduğunu gösterdiğini kontrol eden bir IF deyimi oluşturur. Anahtar türleri, yöntemleri ve özellikleri şunlardır: IfStatement, ExistsPredicate, ScalarSubquery, NamedTableReference, WhereClause, ColumnReferenceExpression, IntegerLiteral, BooleanComparisonExpression ve BooleanNotExpression. GetStepInfo GetStepInfo yöntemini tanımlayın. Bu yöntem, adım adına ek olarak adımın betiğini oluşturmak için kullanılan model öğesi hakkındaki bilgileri ayıklar. İlgi çekici türler ve yöntemler şunlardır: DeploymentPlanContributorContext, DeploymentScriptDomStep, TSqlObject, CreateElementStep, AlterElementStepve DropElementStep. GetElementName TSqlObject için biçimlendirilmiş bir ad oluşturur.
Yardımcı yöntemleri tanımlamak için aşağıdaki kodu ekleyin:
/// <summary> /// The CreateExecuteSql method "wraps" the provided statement script in an "sp_executesql" statement /// Examples of statements that must be so wrapped include: stored procedures, views, and functions /// </summary> private static ExecuteStatement CreateExecuteSql(string statementScript) { // define a new Exec statement ExecuteStatement executeSp = new ExecuteStatement(); ExecutableProcedureReference spExecute = new ExecutableProcedureReference(); executeSp.ExecuteSpecification = new ExecuteSpecification { ExecutableEntity = spExecute }; // define the name of the procedure that you want to execute, in this case sp_executesql SchemaObjectName procName = new SchemaObjectName(); procName.Identifiers.Add(CreateIdentifier("sp_executesql", QuoteType.NotQuoted)); ProcedureReference procRef = new ProcedureReference { Name = procName }; spExecute.ProcedureReference = new ProcedureReferenceName { ProcedureReference = procRef }; // add the script parameter, constructed from the provided statement script ExecuteParameter scriptParam = new ExecuteParameter(); spExecute.Parameters.Add(scriptParam); scriptParam.ParameterValue = new StringLiteral { Value = statementScript }; scriptParam.Variable = new VariableReference { Name = "@stmt" }; return executeSp; } /// <summary> /// The CreateIdentifier method returns a Identifier with the specified value and quoting type /// </summary> private static Identifier CreateIdentifier(string value, QuoteType quoteType) { return new Identifier { Value = value, QuoteType = quoteType }; } /// <summary> /// The CreateCompletedBatchesName method creates the name that will be inserted /// into the temporary table for a batch. /// </summary> private static SchemaObjectName CreateCompletedBatchesName() { SchemaObjectName name = new SchemaObjectName(); name.Identifiers.Add(CreateIdentifier("tempdb", QuoteType.SquareBracket)); name.Identifiers.Add(CreateIdentifier("dbo", QuoteType.SquareBracket)); name.Identifiers.Add(CreateIdentifier(CompletedBatchesVariable, QuoteType.SquareBracket)); return name; } /// <summary> /// Helper method that determines whether the specified statement needs to /// be escaped /// </summary> /// <param name="sqlObject"></param> /// <returns></returns> private static bool IsStatementEscaped(TSqlObject sqlObject) { HashSet<ModelTypeClass> escapedTypes = new HashSet<ModelTypeClass> { Schema.TypeClass, Procedure.TypeClass, View.TypeClass, TableValuedFunction.TypeClass, ScalarFunction.TypeClass, DatabaseDdlTrigger.TypeClass, DmlTrigger.TypeClass, ServerDdlTrigger.TypeClass }; return escapedTypes.Contains(sqlObject.ObjectType); } /// <summary> /// Helper method that creates an INSERT statement to track a batch being completed /// </summary> /// <param name="batchId"></param> /// <param name="batchDescription"></param> /// <returns></returns> private static InsertStatement CreateBatchCompleteInsert(int batchId, string batchDescription) { InsertStatement insert = new InsertStatement(); NamedTableReference batchesCompleted = new NamedTableReference(); insert.InsertSpecification = new InsertSpecification(); insert.InsertSpecification.Target = batchesCompleted; batchesCompleted.SchemaObject = CreateCompletedBatchesName(); // Build the columns inserted into ColumnReferenceExpression batchIdColumn = new ColumnReferenceExpression(); batchIdColumn.MultiPartIdentifier = new MultiPartIdentifier(); batchIdColumn.MultiPartIdentifier.Identifiers.Add(CreateIdentifier(BatchIdColumnName, QuoteType.NotQuoted)); ColumnReferenceExpression descriptionColumn = new ColumnReferenceExpression(); descriptionColumn.MultiPartIdentifier = new MultiPartIdentifier(); descriptionColumn.MultiPartIdentifier.Identifiers.Add(CreateIdentifier(DescriptionColumnName, QuoteType.NotQuoted)); insert.InsertSpecification.Columns.Add(batchIdColumn); insert.InsertSpecification.Columns.Add(descriptionColumn); // Build the values inserted ValuesInsertSource valueSource = new ValuesInsertSource(); insert.InsertSpecification.InsertSource = valueSource; RowValue values = new RowValue(); values.ColumnValues.Add(new IntegerLiteral { Value = batchId.ToString() }); values.ColumnValues.Add(new StringLiteral { Value = batchDescription }); valueSource.RowValues.Add(values); return insert; } /// <summary> /// This is a helper method that generates an if statement that checks the batches executed /// table to see if the current batch has been executed. The if statement will look like this /// /// if not exists(select 1 from [tempdb].[dbo].[$(CompletedBatches)] /// where BatchId = batchId) /// begin /// end /// </summary> /// <param name="batchId"></param> /// <returns></returns> private static IfStatement CreateIfNotExecutedStatement(int batchId) { // Create the exists/select statement ExistsPredicate existsExp = new ExistsPredicate(); ScalarSubquery subQuery = new ScalarSubquery(); existsExp.Subquery = subQuery; subQuery.QueryExpression = new QuerySpecification { SelectElements = { new SelectScalarExpression { Expression = new IntegerLiteral { Value ="1" } } }, FromClause = new FromClause { TableReferences = { new NamedTableReference() { SchemaObject = CreateCompletedBatchesName() } } }, WhereClause = new WhereClause { SearchCondition = new BooleanComparisonExpression { ComparisonType = BooleanComparisonType.Equals, FirstExpression = new ColumnReferenceExpression { MultiPartIdentifier = new MultiPartIdentifier { Identifiers = { CreateIdentifier(BatchIdColumnName, QuoteType.SquareBracket) } } }, SecondExpression = new IntegerLiteral { Value = batchId.ToString() } } } }; // Put together the rest of the statement IfStatement ifNotExists = new IfStatement { Predicate = new BooleanNotExpression { Expression = existsExp } }; return ifNotExists; } /// <summary> /// Helper method that generates a useful description of the step. /// </summary> private static void GetStepInfo( DeploymentScriptDomStep domStep, out string stepDescription, out TSqlObject element) { element = null; // figure out what type of step we've got, and retrieve // either the source or target element. if (domStep is CreateElementStep) { element = ((CreateElementStep)domStep).SourceElement; } else if (domStep is AlterElementStep) { element = ((AlterElementStep)domStep).SourceElement; } else if (domStep is DropElementStep) { element = ((DropElementStep)domStep).TargetElement; } // construct the step description by concatenating the type and the fully qualified // name of the associated element. string stepTypeName = domStep.GetType().Name; if (element != null) { string elementName = GetElementName(element); stepDescription = string.Format(CultureInfo.InvariantCulture, "{0} {1}", stepTypeName, elementName); } else { // if the step has no associated element, just use the step type as the description stepDescription = stepTypeName; } } private static string GetElementName(TSqlObject element) { StringBuilder name = new StringBuilder(); if (element.Name.HasExternalParts) { foreach (string part in element.Name.ExternalParts) { if (name.Length > 0) { name.Append('.'); } name.AppendFormat("[{0}]", part); } } foreach (string part in element.Name.Parts) { if (name.Length > 0) { name.Append('.'); } name.AppendFormat("[{0}]", part); } return name.ToString(); }
Yapılan değişiklikleri SqlRestartableScriptContributor.cs olarak kaydedin.
Ardından sınıf kitaplığını oluşturacaksınız.
Derlemeyi imzalamak ve oluşturmak için
Proje menüsünde MyOtherDeploymentContributor Propertiesöğesine tıklayın.
İmzalama sekmesine tıklayın.
İmzala'ya tıklayın.derleme.
Güçlü bir ad anahtarı dosyası seçin, <Yeni>üzerine tıklayın.
Tanımlayıcı Ad Anahtarı Oluştur iletişim kutusunda, Anahtar dosya adıalanına MyRefKeyyazın.
(isteğe bağlı) Tanımlayıcı ad anahtarı dosyanız için bir parola belirtebilirsiniz.
Tamamtıklayın.
Dosya menüsünde Tümünü Kaydetseçeneğine tıklayın.
Derleme menüsünde Derleme Çözümüöğesine tıklayın.
Ardından, SQL projelerini dağıttığınızda yüklenmesi için derlemeyi yüklemeniz gerekir.
Dağıtım Bileşenini Kurma
Dağıtım katkıda bulunanını yüklemek için derlemeyi ve ilişkili .pdb dosyasını Uzantılar klasörüne kopyalamanız gerekir.
MyOtherDeploymentContributor derlemesini yüklemek için
Ardından, derleme bilgilerini Uzantılar dizinine kopyalayacaksınız. Visual Studio 2022 başlatıldığında, \Microsoft Visual Studio\2022\Enterprise\Common7\IDE\Extensions\Microsoft\SQLDB\DAC dizin ve alt dizinleri%%Program Dosyalarındaki uzantıları belirler ve bunları kullanılabilir hale getirir.
MyOtherDeploymentContributor.dll derleme dosyasını çıkış dizininden %Program Dosyaları%\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\Extensions\Microsoft\SQLDB\DAC dizinine kopyalayın. Varsayılan olarak, derlenmiş .dll dosyanızın yolu YourSolutionPath\YourProjectPath\bin\Debug veya YourSolutionPath\YourProjectPath\bin\Release şeklindedir.
Dağıtım İçericisini Çalıştırın veya Test Edin
Dağıtım katkıda bulunanınızı çalıştırmak veya test etmek için aşağıdaki görevleri gerçekleştirmeniz gerekir:
Derlemeyi planladığınız .sqlproj dosyasına özellikler ekleyin.
MSBuild kullanarak ve uygun parametreleri sağlayarak veritabanı projesini dağıtın.
SQL Projesi (.sqlproj) Dosyasına Özellikler Ekleme
Çalıştırmak istediğiniz katkıda bulunanların kimliğini belirtmek için SQL proje dosyasını her zaman güncelleştirmeniz gerekir. SQL projesini iki yoldan biriyle güncelleştirebilirsiniz:
Gerekli bağımsız değişkenleri eklemek için .sqlproj dosyasını el ile değiştirebilirsiniz. Katkıda bulunanınızın yapılandırma için gerekli herhangi bir katkıda bulunan bağımsız değişkeni yoksa veya derleme katkıda bulunanını çok sayıda projede yeniden kullanmayı düşünmüyorsanız bunu yapmayı seçebilirsiniz. Bu seçeneği belirlerseniz, dosyadaki ilk İçeri Aktarma düğümünden sonra .sqlproj dosyasına aşağıdaki deyimleri ekleyin:
<PropertyGroup> <DeploymentContributors> $(DeploymentContributors); MyOtherDeploymentContributor.RestartableScriptContributor </DeploymentContributors> </PropertyGroup>
İkinci yöntem, gerekli katkı sağlayıcı argümanlarını içeren bir hedef dosyası oluşturmaktır. Bu, birden çok proje için aynı katkıda bulunanı kullanıyorsanız ve varsayılan değerleri içereceğinden katkıda bulunan bağımsız değişkenleri gerekliyse kullanışlıdır. Bu durumda, MSBuild uzantıları yolunda bir hedefler dosyası oluşturun:
%Program Dosyalar%\MSBuild'e gidin.
Hedef dosyalarınızın depolandığı yeni bir "MyContributors" klasörü oluşturun.
Bu dizinde yeni bir "MyContributors.targets" dosyası oluşturun, aşağıdaki metni ekleyin ve dosyayı kaydedin:
<?xml version="1.0" encoding="utf-8"?> <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <DeploymentContributors>$(DeploymentContributors);MyOtherDeploymentContributor.RestartableScriptContributor</DeploymentContributors> </PropertyGroup> </Project>
Katkıda bulunanları çalıştırmak istediğiniz herhangi bir projenin .sqlproj dosyasının içinde, <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets" /> düğümünden sonra .sqlproj dosyasına aşağıdaki deyimi ekleyerek targets dosyasını içeri aktarın:
<Import Project="$(MSBuildExtensionsPath)\MyContributors\MyContributors.targets " />
Bu yaklaşımlardan birini izledikten sonra MSBuild kullanarak komut satırı derlemelerinin parametrelerini geçirebilirsiniz.
Not
Katkıda bulunan kimliğinizi belirtmek için "DeploymentContributors" özelliğini her zaman güncelleştirmeniz gerekir. Bu, katkıda bulunan kaynak dosyanızdaki "ExportDeploymentPlanModifier" özniteliğinde kullanılan kimlikle aynıdır. Bu olmadan, projeyi oluştururken katkıda bulunanınız çalıştırılmaz. "ContributorArguments" özelliği, yalnızca katkıda bulunanınızın çalışması için gerekli olan bağımsız değişkenlere sahipseniz güncellenmelidir.
Veritabanı Projesini Dağıtma
SQL projenizi dağıtmak ve dağıtım raporu oluşturmak için
Projeniz Visual Studio'da normal şekilde yayımlanabilir veya dağıtılabilir. SQL projenizi içeren bir çözüm açın ve Yayımla... seçeneğine tıklayın veya LocalDB'ye hata ayıklama dağıtımı için F5 kullanın. Bu örnekte bir dağıtım betiği oluşturmak için "Yayımla..." iletişim kutusunu kullanıyoruz.
Visual Studio'yu açın ve SQL Projenizi içeren çözümü açın.
Çözüm Gezgini'nde projeye sağ tıklayın ve Yayımla... seçeneğini belirleyin.
Yayımlanacağı sunucu adını ve veritabanı adını ayarlayın.
Diyalog kutusunun altındaki seçeneklerden Betik Oluştur'u seçin. Bu eylem, dağıtım için kullanılabilecek bir betik oluşturur. Betiği yeniden başlatılabilir hale getirmek için IF deyimlerimizin eklendiğini doğrulamak için bu betiği inceleyebiliriz.
Sonuçta elde edilen dağıtım betiğini inceleyin. "Dağıtım Öncesi Betik Şablonu" etiketli bölümden hemen önce aşağıdaki Transact-SQL söz dizimine benzer bir şey görmeniz gerekir:
:setvar CompletedBatches __completedBatches_CompareProjectDB_cd1e348a-8f92-44e0-9a96-d25d65900fca :setvar TotalBatchCount 17 GO if OBJECT_ID(N'tempdb.dbo.$(CompletedBatches)', N'U') is null begin use tempdb create table [dbo].[$(CompletedBatches)] ( BatchId int primary key, Description nvarchar(300) ) use [$(DatabaseName)] end
Dağıtım betiğinin ilerleyen bölümlerinde, her toplu işlemde özgün deyimi çevreleyen bir IF deyimi görürsünüz. Örneğin, CREATE SCHEMA deyimi için aşağıdaki T-SQL betiği görünebilir:
IF NOT EXISTS (SELECT 1 FROM [tempdb].[dbo].[$(CompletedBatches)] WHERE [BatchId] = 0) BEGIN EXECUTE sp_executesql @stmt = N'CREATE SCHEMA [Sales] AUTHORIZATION [dbo]'; SET NOCOUNT ON; INSERT [tempdb].[dbo].[$(CompletedBatches)] (BatchId, Description) VALUES (0, N'CreateElementStep Sales batch 0'); SET NOCOUNT OFF; END
CREATE SCHEMA öğesinin, IF deyimi içindeki execute sp_executesql deyiminin içine alınması gereken deyimlerden biri olduğuna dikkat edin. CREATE TABLE gibi deyimler EXECUTE sp_executesql deyimini gerektirmez ve aşağıdaki örneğe benzer:
IF NOT EXISTS (SELECT 1 FROM [tempdb].[dbo].[$(CompletedBatches)] WHERE [BatchId] = 1) BEGIN CREATE TABLE [Sales].[Customer] ( [CustomerID] INT IDENTITY (1, 1) NOT NULL, [CustomerName] NVARCHAR (40) NOT NULL, [YTDOrders] INT NOT NULL, [YTDSales] INT NOT NULL ); SET NOCOUNT ON; INSERT [tempdb].[dbo].[$(CompletedBatches)] (BatchId, Description) VALUES (1, N'CreateElementStep Sales.Customer batch 0'); SET NOCOUNT OFF; END
Not
Hedef veritabanıyla aynı olan bir veritabanı projesi dağıtırsanız, sonuçta elde edilen rapor çok anlamlı olmaz. Daha anlamlı sonuçlar için, değişiklikleri bir veritabanına dağıtın veya yeni bir veritabanı dağıtın.
Oluşturulan dacpac dosyası kullanılarak komut satırı dağıtımı
SQL proje derlemesinden çıkış yapıtı bir dacpac dosyasıdır. Komut satırından şemayı dağıtmak için bir dacpac dosyası kullanılabilir ve bu dosya derleme makinesi gibi farklı bir makineden dağıtımı etkinleştirebilir. SqlPackage, kullanıcıların diğer eylemlerin yanında bir dacpac dağıtmasına veya dağıtım betiği oluşturmasına olanak tanıyan çok çeşitli seçeneklere sahip bir komut satırı yardımcı programıdır. Daha fazla bilgi için bkz. SqlPackage.exe.
Not
Tanımlanan DeploymentContributors özelliğiyle projelerden oluşturulan dacpac'leri başarıyla dağıtmak için, dağıtım katkıda bulunanlarınızı içeren DLL'ler kullanılan makineye yüklenmelidir. Bunun nedeni, dağıtımın başarıyla tamamlanması için gerekli olarak işaretlenmeleridir.
Bu gereksinimi önlemek için dağıtım katkıda bulunanını .sqlproj dosyasından hariç tutun. Bunun yerine, AdditionalDeploymentContributors parametresiyle SqlPackage kullanarak dağıtım sırasında çalıştırılacak katkıda bulunanları belirtin. Bu, belirli bir sunucuya dağıtım gibi özel durumlar için yalnızca katkıda bulunan kullanmak istediğiniz durumlarda kullanışlıdır.
Sonraki Adımlar
Dağıtım planlarında yürütülmeden önce diğer değişiklik türleriyle denemeler yapabilirsiniz. Yapmak isteyebileceğiniz diğer bazı değişiklik türleri şunlardır:
Bir sürüm numarasını kendisiyle ilişkilendiren tüm veritabanı nesnelerine genişletilmiş özellik ekleme.
Dağıtım betiklerinden ek tanılama yazdırma deyimleri veya açıklamaları ekleme veya kaldırma.
Ayrıca Bkz.
Derleme ve Dağıtım Katkıda Bulunanlarını Kullanarak Veritabanı Derleme ve Dağıtımını Özelleştirme
Adım Adım Kılavuz: Model İstatistikleri Oluşturmak için Veritabanı Proje Çalıştırmasını Genişletme İşlemi
İzlenecek Yol: Dağıtım Planını Analiz Etmek İçin Veritabanı Projesi Dağıtımını Genişletme