【问题标题】:how to map column if exists otherwise empty如果存在则如何映射列,否则为空
【发布时间】:2019-11-05 02:56:52
【问题描述】:

我正在尝试将属性映射到公式以选择值,如果该列存在,则为默认值

我尝试了以下

mapper.Map(x => x.GroupId).Formula("(select case when exists (select * from INFORMATION_SCHEMA.COLUMNS SYS_COLS_TBL WHERE SYS_COLS_TBL.TABLE_NAME ='Azure' AND SYS_COLS_TBL.COLUMN_NAME = 'GroupId') then this_.GroupId else '' end)");

我收到一个错误 SqlException:列名“GroupId”无效。

【问题讨论】:

    标签: nhibernate


    【解决方案1】:

    此 SQL 语句将返回名称为“Azure”的所有表

    select * from INFORMATION_SCHEMA.COLUMNS SYS_COLS_TBL 
     WHERE SYS_COLS_TBL.TABLE_NAME ='Azure' 
       AND SYS_COLS_TBL.COLUMN_NAME = 'GroupId'
    

    但是,可能有例如两个这样的表.. 但在不同的架构。如果发生这种情况,我们可以查询dbo.Azure .. 而SomeOtherSchema.Azure 的列是GroupId。这将解决它:

    select * from INFORMATION_SCHEMA.COLUMNS SYS_COLS_TBL 
     WHERE SYS_COLS_TBL.TABLE_NAME ='Azure' 
       AND SYS_COLS_TBL.COLUMN_NAME = 'GroupId'
       AND SYS_COLS_TBL.TABLE_SCHEMA = 'dbo'
    

    此外,为了支持更复杂的查询(JOIN 关联),请移除 this_。

    代替:

    then this_.GroupId else '' end)
    

    使用:

    then GroupId else '' end)
    

    NHibernate 将根据上下文提供适当的别名

    【讨论】:

    【解决方案2】:

    SQL 语句要求对表和列的所有引用确实存在。因此,您会收到 Invalid column name 'GroupId' 错误。

    执行此类操作的通常方法是使用动态 sql (sp_executesql @sql):

    DECLARE @sql NVARCHAR(MAX) = '
    SELECT '+
        (CASE WHEN EXISTS (SELECT *
                           FROM INFORMATION_SCHEMA.COLUMNS 
                           WHERE TABLE_SCHEMA = 'dbo' AND --assuming the schema is dbo
                                 TABLE_NAME = 'Azure' AND
                                 COLUMN_NAME = 'GroupId'
                          )
              then 'GroupId'
              else 'NULL as GroupId'
         end) + '
    FROM Azure';
    
    exec sp_executesql @sql
    

    但这不起作用,因为您已经在 SQL 语句的上下文中,并且无法在其中注入动态 sql。

    要解决这个问题有几个解决方案:

    1. 正确的解决方案:在数据库中创建缺失的列。

    2. 痛苦的解决方案:将对象映射到存储过程,该存储过程将执行类似于上述的动态 SQL。

    3. 非常痛苦的解决方案:照常映射您可能丢失的列。在构建工厂之前 - 内省您的模型并删除缺少列的映射或将它们的映射更改为公式。这类似于 NHibernate 的 Configuration.ValidateSchema 方法,但不是抛出错误 - 您需要从映射中删除这些列。

    【讨论】:

      猜你喜欢
      • 2013-08-26
      • 2014-06-19
      • 1970-01-01
      • 2022-12-05
      • 2013-06-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-01
      • 1970-01-01
      相关资源
      最近更新 更多