将大量数据加载到Oracle的业务对象的List集合中

时间:2012-09-26 16:52:54

标签: c# xml linq oracle

我需要一种方法来优化从Oracle数据库到自定义业务对象列表的数百万条记录的数据检索。从Oracle返回的数据是XML格式的,我需要一种方法将其序列化为业务对象列表。

我编写的代码工作正常,但是在将XML加载到内存期间执行需要很长时间,特别是当代码命中时:

var xDoc = XDocument.Load(xmlReader);   

代码:

//Custom Business object  
 public class AccountType
    {
        public int AccountTypeID { get; set; }
        public string AccountCode { get; set; }
        public string BookType { get; set; }
        public int Status { get; set; }
    }

//Code that retrieves data from Oracle DB

  using (OracleConnection objOracleConnection = new OracleConnection(strConnectionString))
            {
                using (OracleCommand orclCmd = objOracleConnection.CreateCommand())
                {
                    try
                    {

                        orclCmd.CommandText = strXMLSQL;
                        orclCmd.BindByName = true;
                        orclCmd.XmlCommandType = OracleXmlCommandType.Query;
                        orclCmd.XmlQueryProperties.RootTag = "AccountData";
                        orclCmd.XmlQueryProperties.RowTag = "ROW";

                        objOracleConnection.Open();
                        XmlReader xmlReader = orclCmd.ExecuteXmlReader();
                        var xDoc = XDocument.Load(xmlReader);                             
                        List<AccountType> accountTypes = (from data in xDoc.Root.Elements("ROW")
                                                              select new AccountType
                                                              {
                                                                  AccountTypeID = data.GetIntXMLElementValue("ACCOUNTTYPEID"),
                                                                  AccountCode = data.GetStringXMLElementValue("ACCOUNTCODE"),
                                                                  BookType = data.GetStringXMLElementValue("BOOKTYPE"),
                                                                  Status = data.GetIntXMLElementValue("STATUS")
                                                              }).ToList();

                    }
                    catch (OracleException oracleEx)
                    {
                        throw oracleEx;
                    }
                    catch (Exception generalEx)
                    {
                        throw generalEx;
                    }
                    finally
                    {
                        objOracleConnection.Close();
                    }
 }

非常感谢任何帮助。

谢谢!

2 个答案:

答案 0 :(得分:0)

您是否一次需要数百万条记录?

数据是否以XML格式存储在数据库中?如果不是,您可以使用ExexcutePageReader而不是ExecuteXmlReader

如果必须是XML,则可以通过调用id在lastId加1和lastId加上pageLength

之间的记录来实现自己的寻呼机

答案 1 :(得分:0)

分页是一种选择。也可以在调用ToList()之前使用PLINQ进行线程处理,因为这是您获取命中的位置。我还要补充一点,删除XDocument加载可能会有所帮助。尝试反序列化xml。假设您的XML看起来像这样

<ROWSET>
    <ROW>
        <AccountData>
            <ACCOUNTTYPEID>1</ACCOUNTTYPEID>
            <ACCOUNTCODE>ABC</ACCOUNTCODE>
            <BOOKTYPE>FOO</BOOKTYPE>
            <STATUS>10</STATUS>
        </AccountData>
    </ROW>
    <ROW>
        <AccountData>
            <ACCOUNTTYPEID>2</ACCOUNTTYPEID>
            <ACCOUNTCODE>XYZ</ACCOUNTCODE>
            <BOOKTYPE>BAR</BOOKTYPE>
            <STATUS>20</STATUS>
        </AccountData>
    </ROW>
</ROWSET>

您可以设置以下合同:

[DataContract(Namespace = "")]
public class AccountData
{
    [DataMember(Name = "ACCOUNTTYPEID")]
    public int Id { get; set; }
}

[DataContract(Name = "ROW", Namespace = "")]
public class Row
{
    [DataMember(Name = "AccountData")]
    public AccountData Data { get; set; }
}

[CollectionDataContract(Name="ROWSET", Namespace = "")]
public class RowSet
    : List<Row>
{
}

并像这样反序列化

var s = new DataContractSerializer(typeof(RowSet));
var o = s.ReadObject(xmlreader) as RowSet;

这可以避免XDocument加载和LINQ-XML开销。