C# 如何检测SELECT中的列是否可以为空?

C# 如何检测SELECT中的列是否可以为空?,c#,sql-server,sql-server-data-tools,dac,scriptdom,C#,Sql Server,Sql Server Data Tools,Dac,Scriptdom,我在设计时使用DacFx创建一个C数据层,它是从SSDT数据库项目中的sql文件生成的。看看我的,看看我在说什么 我正在生成DTO对象,这些对象表示从存储过程的SELECT语句返回的行。为了确定DTO上的属性是否应该是可为null的值类型,我将检查该列在其来源的表中是否可以为null。如果你想知道那是什么样子,下面是代码。tSqlObject这里是存储过程的tSqlObject实例 var bodyColumnTypes = tSqlObject.GetReferenced(dac.Proced

我在设计时使用DacFx创建一个C数据层,它是从SSDT数据库项目中的sql文件生成的。看看我的,看看我在说什么

我正在生成DTO对象,这些对象表示从存储过程的SELECT语句返回的行。为了确定DTO上的属性是否应该是可为null的值类型,我将检查该列在其来源的表中是否可以为null。如果你想知道那是什么样子,下面是代码。tSqlObject这里是存储过程的tSqlObject实例

var bodyColumnTypes = tSqlObject.GetReferenced(dac.Procedure.BodyDependencies)
    .Where(x => x.ObjectType.Name == "Column")
    .GroupBy(bd => string.Join(".", bd.Name.Parts))
    .Select(grp => grp.First())
    .ToDictionary(
        key => string.Join(".", key.Name.Parts),
        val => new DataType
        {
            Map = DataTypeHelper.Instance.GetMap(TypeFormat.SqlServerDbType, val.GetReferenced(dac.Column.DataType).First().Name.Parts.Last()),
            Nullable = dac.Column.Nullable.GetValue<bool>(val)
        },
        StringComparer.InvariantCultureIgnoreCase);
问题是我没有考虑左或右外部联接,这也可能使值为null


如何确定SELECT语句中的列是否可以为null?或者,如果这个问题太宽泛,我如何确定该列是否来自外部联接的表?

我想我找到了答案。给定SELECT语句的QuerySpecification,我可以使用以下方法获取联接列表:

var joins = querySpecification.FromClause.TableReferences.OfType<QualifiedJoin>();

每个QualifiedJoin对象都有一个QualifiedJoint属性,该属性是一个枚举,将被设置为内部、左外部、右外部或全外部。

老实说,我认为您永远都无法获得100%的正确性。对于justselect语句,您可能可以,但由于这是一个数据层,您将如何处理存储过程?如果这些过程包含对其他过程的调用或包含动态sql怎么办?这些表是否不表示不同的对象?如果是这样,那么您的select不应该返回两个单独的对象,其中一个可以为null,而不是一个表示查询中所有字段的对象吗?@SeanLange,您提出了一些好的观点。我还没有测试这些场景。我想我可以解决嵌套过程的问题。动态sql可能要复杂得多。但我不认为我需要解决所有可能的情况,我的项目才能对人们有用。我允许通过使我的所有类成为部分类来扩展它,并将虚拟添加到所有方法中。这可能是一种例外情况,有些人可能必须手动编写代码,但他们仍然可以使用生成的其余代码。@KyleW,我想我明白你的意思,但即使我更改了实现,按照列的来源表将列分组为对象,问题仍然是如何确定这些表是否保持连接,因为我仍然需要知道是否实例化该对象,否?@adam0101如果表中需要一列,并且结果集中该列为null,并且该表中的所有列都为null,则该对象应为null