2016-11-17 1 views
0

J'essaie de créer une analyse de code personnalisée pour les projets de base de données. J'ai quelques validations écrites pour des tables qui fonctionnent bien actuellement. Cependant, ma première validation pour les vues ne semble pas fonctionner. Lors du débogage des règles, il sera percé une fois dans la règle. À ce moment, ruleExecutionContext.ModelElement est null. J'ai cherché une autre classe à utiliser en plus de la classe de type vue, mais cela semble être la bonne à utiliser. J'utilise actuellement cette version de SSDT: SSDT_14.0.61021.0_EN avec Visual Studio 2015. Je ne comprends pas pourquoi les tests de table fonctionnent, mais pas les vues.Analyse de code Validation des vues dans DACPAC à l'aide de DacFX

[ExportCodeAnalysisRule(NestedViewRule.RuleId, 
    NestedViewRule.RuleDisplayName, 
    Description = NestedViewRule.RuleDisplayName, 
    Category = Constants.Performance, 
    RuleScope = SqlRuleScope.Model)] 
public sealed class NestedViewRule : SqlCodeAnalysisRule 
{ 
    public const string RuleId = Constants.RuleNameSpace + "SRP0001"; 
    public const string RuleDisplayName = "Views should not use other views as a data source"; 
    public const string Message = "View {0} uses view {1} as a datasource. This has a negative impact upon performance."; 

    public NestedViewRule() 
    { 
     SupportedElementTypes = new[] { ModelSchema.View }; // View.TypeClass, neither seems to work 
    } 

    public override IList<SqlRuleProblem> Analyze(SqlRuleExecutionContext ruleExecutionContext) 
    { 
     List<SqlRuleProblem> problems = new List<SqlRuleProblem>(); 
     TSqlObject sqlObj = ruleExecutionContext.ModelElement; 
     if (sqlObj != null) 
     { 
      foreach (var child in sqlObj.GetReferenced(DacQueryScopes.All).Where(x => x.ObjectType == View.TypeClass)) 
      { 
       string msg = string.Format(Message, RuleUtils.GetElementName(ruleExecutionContext, sqlObj), RuleUtils.GetElementName(ruleExecutionContext, child)); 
       problems.Add(new SqlRuleProblem(msg, sqlObj) /*{ Severity = SqlRuleProblemSeverity.Error } */); 
      } 
     } 

     return problems; 
    } 
} 

Voici une de mes règles de table qui travaillent actuellement au cas où quelqu'un est intéressé:

[ExportCodeAnalysisRule(TableHasPrimaryKeyRule.RuleId, 
    TableHasPrimaryKeyRule.RuleDisplayName, 
    Description = TableHasPrimaryKeyRule.RuleDisplayName, 
    Category = Constants.BestPractice, 
    RuleScope = SqlRuleScope.Element)] 
public sealed class TableHasPrimaryKeyRule : SqlCodeAnalysisRule 
{ 
    public const string RuleId = Constants.RuleNameSpace + "SRB0002"; 
    public const string RuleDisplayName = "Tables should have a primary key."; 
    public const string Message = "Table {0} does not have a primary key."; 

    public TableHasPrimaryKeyRule() 
    { 
     SupportedElementTypes = new[] { ModelSchema.Table }; 
    } 

    public override IList<SqlRuleProblem> Analyze(SqlRuleExecutionContext ruleExecutionContext) 
    { 
     List<SqlRuleProblem> problems = new List<SqlRuleProblem>(); 
     TSqlObject sqlObj = ruleExecutionContext.ModelElement; 
     if (sqlObj != null) 
     { 
      var child = sqlObj.GetChildren(DacQueryScopes.All).FirstOrDefault(x => x.ObjectType == PrimaryKeyConstraint.TypeClass); 
      if (child == null) 
      { 
       string msg = string.Format(Message, RuleUtils.GetElementName(ruleExecutionContext, sqlObj)); 
       problems.Add(new SqlRuleProblem(msg, sqlObj)); 
      } 
     } 

     return problems; 
    } 
} 

Répondre

1

Ok, je présente mes excuses, mais après je l'ai posté je remarquai que j'utilisais RuleScope = SqlRuleScope.Model pour la vérification de la vue et l'élément pour les tables. J'ai alors déduit que forçait le modèle de visiteur pour l'enregistrement de vue à être ignoré, et le modèle à me passer le temps.

La modification de l'attribut pour faire correspondre les contrôles de table à l'aide de RuleScope = SqlRuleScope.Element a résolu le problème.

+0

Oui, la portée du modèle est vraiment juste pour quand vous devez faire un seul passage (par exemple si votre conception scanne tous les objets et drapeaux sur les problèmes corrélés.) Vous pouvez interroger le modèle pour les types d'éléments (eg model.GetObjects()) mais la meilleure chose à faire est d'utiliser la portée de l'élément si vous voulez une analyse élément par élément –