C# Spring.Net 使用对象映射(RowMapper)返回数据库查询到的结果集

来源:互联网 发布:seed网络加速器官网 编辑:程序博客网 时间:2024/05/20 08:02

在数据库访问的时候,很多情况下从数据库返回的是一个结果集(List),怎么样把它转换为我们在C#代码中定义的实体类型?

Spring.Net定义了三组接口和委托用于回调,开发人员需要自己实现或定义这些回调方法

(1)IResultSetExtractor/ResultSetExtractorDelegate:传递一个IDataReader对象,开发人员可以利用该对象迭代数据并返回结果对象。

(2)IRowCallback/RowCallbackDelegate:传递一个IDataReader对象,可用于处理当前行。返回值为void,因此在实现IRowCallback接口时一般将类实现为有状态的(按:也就是说实现类需要定义自己的字段来保存回调的结果),在使用匿名委托时,一般用本地变量来保存回调的结果。

(3)IRowMapper/RowMapperDelegate:传递一个IDataReader对象,用以处理当前行并返回一个对应于当前行的对象。

我们这次主要讲解一下第三种.

IRowMapper可以让开发人员专注于如何将结果集中的一行映射为一个对象。框架会负责使用IDataReader进行迭代并创建一个IList来保存结果对象.

Dao层的代码如下:

//必须要继承AdoDaoSupport,//AdoDaoSupport中集成了所有连接数据库,执行访问数据库,关闭数据的所有操作public class PersonDao:AdoDaoSupport{     public IList<Person> GetPersonInfoDetailsByPersonId(string personId)        {            //定义返回 的对象            IList<Person> result = new List<Person>();            //定义用于装载参数的集合            IDbParameters parameters = AdoTemplate.CreateDbParameters();            //添加参数            parameters.AddWithValue("PersonId", new Guid(personId));            //使用QueryWithRowMapper方法访问数据库,返回结果集            result = AdoTemplate.QueryWithRowMapper<Person>(                CommandType.StoredProcedure,"SP_GetPersonInfoByPersonId", new PersonMapper<Person>(), parameters);            return result;        }}
PersonMapper的定义如下:

逐行将数据转换为实体类

 public class PersonMapper<T> : IRowMapper<T> where T : Person, new()    {        T IRowMapper<T>.MapRow(IDataReader dataReader, int rowNum)        {            T view = new T();            if (DataReaderRowFilter.RowFilter(dataReader, "PersonId"))                view.PersonId = dataReader.GetValueOrDefault<Guid>("PersonId");            if (DataReaderRowFilter.RowFilter(dataReader, "PersonName"))                view.PersonName = dataReader.GetValueOrDefault<String>("PersonName");            if (DataReaderRowFilter.RowFilter(dataReader, "Age"))                view.Age = dataReader.GetValueOrDefault<int>("Age");            return view;        }    }
DataReaderRowFilter.RowFilter定义如下:

判断DataReader中是否有某列

 public class DataReaderRowFilter    {        public static bool RowFilter(IDataReader dataReader, string columnName)        {            dataReader.GetSchemaTable().DefaultView.RowFilter = string.Format("ColumnName='{0}'", columnName);            return dataReader.GetSchemaTable().DefaultView.Count > 0;        }    }
GetValueOrDefault定义如下:

 public static T GetValueOrDefault<T>(this IDataReader reader, string columnName)        {            int index = reader.GetOrdinal(columnName);            T returnValue = default(T);            if (!reader.IsDBNull(index))            {                returnValue = (T)Convert.ChangeType(reader[columnName], typeof(T));                //returnValue = (T)reader[columnName];            }            return returnValue;        }

如果映射的逻辑比较少,并且需要使用访问本地变量的时候,使用委托会更加方便(参考官方文档):

 public virtual IList<Customer> GetCustomersWithDelegate()        {            return AdoTemplate.QueryWithRowMapperDelegate<Customer>(CommandType.Text, cmdText,                        delegate(IDataReader dataReader, int rowNum)                            {                                Customer customer = new Customer();                                customer.Address = dataReader.GetString(0);                                customer.City = dataReader.GetString(1);                                customer.CompanyName = dataReader.GetString(2);                                customer.ContactName = dataReader.GetString(3);                                customer.ContactTitle = dataReader.GetString(4);                                customer.Country = dataReader.GetString(5);                                customer.Fax = dataReader.GetString(6);                                customer.Id = dataReader.GetString(7);                                customer.Phone = dataReader.GetString(8);                                customer.PostalCode = dataReader.GetString(9);                                customer.Region = dataReader.GetString(10);                                return customer;                            });        }



0 0