C# 使用DacFX对DACPAC中的视图进行代码分析验证

C# 使用DacFX对DACPAC中的视图进行代码分析验证,c#,database-project,dacpac,C#,Database Project,Dacpac,我正在尝试为数据库项目创建自定义代码分析。我为目前运行良好的表编写了一些验证。然而,我对视图的第一次验证似乎不起作用。在调试规则时,它实际上会破译规则一次,而且只有一次。此时ruleExecutionContext.ModelElement为空。除了视图类型类之外,我已经四处寻找了另一个要使用的类,但它似乎是正确的。我目前正在使用这个版本的SSDT:SSDT_14.0.61021.0_EN以及Visual Studio 2015。我完全不知道为什么表测试可以工作,但是视图不能 [ExportCo

我正在尝试为数据库项目创建自定义代码分析。我为目前运行良好的表编写了一些验证。然而,我对视图的第一次验证似乎不起作用。在调试规则时,它实际上会破译规则一次,而且只有一次。此时ruleExecutionContext.ModelElement为空。除了视图类型类之外,我已经四处寻找了另一个要使用的类,但它似乎是正确的。我目前正在使用这个版本的SSDT:SSDT_14.0.61021.0_EN以及Visual Studio 2015。我完全不知道为什么表测试可以工作,但是视图不能

[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;
    }
}
[ExportCodeAnalysisRule(NestedViewRule.RuleId,
NestedViewRule.RuleDisplayName,
Description=NestedViewRule.RuleDisplayName,
类别=常数。性能,
RuleScope=SqlRuleScope.Model)]
公共密封类NestedViewRule:SqlCodeAnalysisRule
{
公共常量字符串RuleId=Constants.RuleNameSpace+“SRP0001”;
public const string RuleDisplayName=“视图不应将其他视图用作数据源”;
public const string Message=“视图{0}使用视图{1}作为数据源。这对性能有负面影响。”;
公共嵌套视图规则()
{
SupportedElementTypes=new[]{ModelSchema.View};//View.TypeClass,两者似乎都不起作用
}
公共重写IList分析(SqlRuleExecutionContext ruleExecutionContext)
{
列表问题=新列表();
TSqlObject sqlObj=ruleExecutionContext.ModelElement;
if(sqlObj!=null)
{
foreach(sqlObj.GetReferenced(DacQueryScopes.All)中的var子级,其中(x=>x.ObjectType==View.TypeClass))
{
string msg=string.Format(消息,RuleUtils.GetElementName(ruleExecutionContext,sqlObj),RuleUtils.GetElementName(ruleExecutionContext,child));
添加(新的SqlRuleProblem(msg,sqlObj)/*{Severity=SqlRuleProblemSeverity.Error}*/);
}
}
退货问题;
}
}
以下是我目前的工作表规则之一,以防有人感兴趣:

[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;
    }
}
[ExportCodeAnalysisRule(TableHasPrimaryKeyRule.RuleId,
TableHasPrimaryKeyRule.RuleDisplayName,
Description=TableHasPrimaryKeyRule.RuleDisplayName,
类别=常数。最佳实践,
RuleScope=SqlRuleScope.Element)]
公共密封类TableHasPrimaryKeyRule:SqlCodeAnalysisRule
{
公共常量字符串RuleId=Constants.RuleNameSpace+“SRB0002”;
public const string RuleDisplayName=“表应具有主键。”;
public const string Message=“表{0}没有主键。”;
公共表hasPrimaryKeyRule()
{
SupportedElementTypes=new[]{ModelSchema.Table};
}
公共重写IList分析(SqlRuleExecutionContext ruleExecutionContext)
{
列表问题=新列表();
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(消息,RuleUtils.GetElementName(ruleExecutionContext,sqlObj));
添加(新的SqlRuleProblem(msg,sqlObj));
}
}
退货问题;
}
}

好的,很抱歉,但是在我发布它之后,我注意到我正在使用RuleScope=SqlRuleScope.Model进行视图检查,使用元素进行表检查。然后我推断,这迫使视图注册的访问者模式被忽略,模型被一次性传递给我


使用RuleScope=SqlRuleScope.Element更改属性以匹配表检查,修复了该问题。

Yep,模型范围实际上仅适用于需要执行单个过程的情况(例如,如果您的设计扫描了相关问题的所有对象和标志。您可以查询模型中的元素类型(例如model.GetObjects()调用)但是,如果需要逐个元素的分析,最好使用元素范围