使用NHibernate调用存储过程并填充DataTable是否可行?

3

我已经知道如何使用NHibernate调用存储过程并填充DTO(如此处所述)。

但是,我想知道是否可以使用NHibernate中的ResultTransformer概念以相同方式填充DataTable,或者是否有其他推荐的方法?

我更喜欢使用NHibernate中的ResultTransformer概念。 但是,我不知道是否可行以及如何实现。 有其他人尝试过这个吗?


1
看起来有人尝试并取得了一些成功 :-) http://www.codewrecks.com/blog/index.php/2010/10/07/load-a-strongly-typed-dataset-from-a-stored-with-nhibernate/ - jbl
@jbl,感谢您的参考,我已经使用了这个概念并将解决方案作为答案提供了:-)。请看一下。 - Baig
NHibernate在这种情况下只是噪音。如果需要,只需从中获取连接并使用DataAdapter即可。 - Diego Mijelshon
2个回答

7
我使用 这里 描述的ResultTransformer概念,想出了以下解决方案:
  public class DataTableResultTransformer : IResultTransformer
  {
    private DataTable dataTable;

    public IList TransformList(IList collection)
    {
      var rows = collection.Cast<DataRow>().ToList();
      rows.ForEach(dataRow => dataTable.Rows.Add(dataRow));
      return new List<DataTable> { dataTable };
    }

    public object TransformTuple(object[] tuple, string[] aliases)
    {
      //Create the table schema based on aliases if its not already done
      CreateDataTable(aliases);

      //Create and Fill DataRow
      return FillDataRow(tuple, aliases);
    }

    private DataRow FillDataRow(object[] tuple, string[] aliases)
    {
      DataRow dataRow = dataTable.NewRow();
      aliases.ToList().ForEach(alias =>
                                 {
                                   dataRow[alias] = tuple[Array.FindIndex(aliases, colName => colName == alias)];
                                 });
      return dataRow;
    }

    private void CreateDataTable(IEnumerable<string> aliases)
    {
      if (dataTable == null)
      {
        dataTable = new DataTable();
        aliases.ToList().ForEach(alias => dataTable.Columns.Add(alias));
      }
    }
  }

并按以下方式使用:

    using (ISession session = sessionFactory.OpenSession())
    {
      var sqlQuery = session.CreateSQLQuery("SELECT ID, NAME, ADDRESS FROM CUSTOMER");
      var transformedQuery = sqlQuery.SetResultTransformer(new DataTableResultTransformer());
      return transformedQuery.List().Single();
    }

我刚刚创建了一个自定义的ResultTransformer,并在我的SQL查询中使用它来根据我的DataTableResultTransformer逻辑转换查询结果。
TransformTupple方法会针对结果集中的每个项目进行调用。元组包含数据,而别名包含数据的名称。因此,我们几乎拥有构建和填充DataTable所需的所有内容。一旦TransformTupple方法将结果集的所有项目转换完毕,就会在最后调用TransformList方法。集合参数包含我们在TransformTupple方法中转换为DataRow的所有项目。因此,在这里,我们可以轻松地使用DataRows填充我们的DataTable并返回。
希望这对于其他处理相同情况的人有所帮助。

1
这实际上不起作用,因为每个列都将转换为“ string”。您需要使用正确的数据类型设置“ DataTable”列,如果第一行中存在空值,则无法完成此操作。 - Jonathan Allen

0

更新的示例,考虑了列数据类型

[SuppressMessage("Design", "CA1001")]
public class DataTableResultTransformer : IResultTransformer
{
    readonly Type?[] m_DataTypeOverrides = Array.Empty<Type?>();
    readonly DataTable m_DataTable = new DataTable();

    /// <summary>
    /// Initializes a new instance of the <see cref="DataTableResultTransformer"/> class.
    ///
    /// Only use this constructor if none of the columns are nullable.
    /// </summary>
    /// <remarks>Warning: If a field is NULL in the first row, that entire column will be cast as a String.</remarks>
    public DataTableResultTransformer()
    {
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="DataTableResultTransformer"/> class.
    ///
    /// 1. If dataTypeOverrides for a given column is not null, it is used.
    /// 2. If the field is not null for the first row, then that field's data type if used.
    /// 3. If both the dataTypeOverride and the field in the first row are null, the column's data type is String.
    /// </summary>
    /// <param name="dataTypeOverrides">The expected data types.</param>
    public DataTableResultTransformer(params Type?[] dataTypeOverrides)
    {
        m_DataTypeOverrides = dataTypeOverrides;
    }

    public IList TransformList(IList collection)
    {
        return new List<DataTable> { m_DataTable };
    }

    public object TransformTuple(object[] tuple, string[] aliases)
    {
        if (tuple == null || tuple.Length == 0)
            throw new ArgumentException($"{nameof(tuple)} is null or empty.", nameof(tuple));

        if (aliases == null || aliases.Length == 0)
            throw new ArgumentException($"{nameof(aliases)} is null or empty.", nameof(aliases));

        if (m_DataTable.Columns.Count == 0)
        {
            //Create the DataTable if this is the first row
            for (var i = 0; i < aliases.Length; i++)
            {
                var col = m_DataTable.Columns.Add(aliases[i]);
                if (i < m_DataTypeOverrides.Length && m_DataTypeOverrides[i] != null)
                    col.DataType = m_DataTypeOverrides[i];
                else if (tuple[i] != null && tuple[i] != DBNull.Value)
                    col.DataType = tuple[i].GetType();
            }
        }

        return m_DataTable.Rows.Add(tuple);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接