How to implement IDataReader?
I've a XML looking like this :
<resultset>
<datarow>
<datacol>Row 1 - Col 1</datacol>
<datacol>Row 1 - Col 2</datacol>
<datacol>Row 1 - Col 3</datacol>
...
</datarow>
...
</resultset>
...
My question is, how can I implement the IDataReader interface with this XML? I'm lost...
I've developed this :
public sealed class SybaseDat开发者_如何学PythonaReader : IDataReader
{
private DataSet _dataSet = new DataSet();
#region IDataReader methods implementation
// ...
}
I'm on the good way?
Thanks for constructive and well explained posts.
I wrote a simple file reader implementation. You could easily adapt this to read a xml file:
public class MyFileDataReader : IDataReader
{
protected StreamReader Stream { get; set; }
protected object[] Values;
protected bool Eof { get; set; }
protected string CurrentRecord { get; set; }
protected int CurrentIndex { get; set; }
public MyFileDataReader(string fileName)
{
Stream = new StreamReader(fileName);
Values = new object[this.FieldCount];
}
Remember that IDataReader has several methods that you dont need to implement depending on your scenario. But probably there are some methods implementations that you will not be able to avoid:
public void Close()
{
Array.Clear(Values, 0, Values.Length);
Stream.Close();
Stream.Dispose();
}
public int Depth
{
get { return 0; }
}
public DataTable GetSchemaTable()
{
// avoid to implement several methods if your scenario do not demand it
throw new NotImplementedException();
}
public bool IsClosed
{
get { return Eof; }
}
public bool NextResult()
{
return false;
}
public bool Read()
{
CurrentRecord = Stream.ReadLine();
Eof = CurrentRecord == null;
if (!Eof)
{
Fill(Values);
CurrentIndex++;
}
return !Eof;
}
private void Fill(object[] values)
{
//To simplify the implementation, lets assume here that the table have just 3
//columns: the primary key, and 2 string columns. And the file is fixed column formatted
//and have 2 columns: the first with width 12 and the second with width 40. Said that, we can do as follows
values[0] = null;
values[1] = CurrentRecord.Substring(0, 12).Trim();
values[2] = CurrentRecord.Substring(12, 40).Trim();
// by default, the first position of the array hold the value that will be
// inserted at the first column of the table, and so on
// lets assume here that the primary key is auto-generated
// if the file is xml we could parse the nodes instead of Substring operations
}
public int RecordsAffected
{
get { return -1; }
}
To implement IDataReader, is also mandatory to implement the IDisposable and the IDataRecord interfaces.
The IDisposable is easy, but the IDataRecord can be painful. Again, in this scenario there are some methods implementations that we are not able to avoid:
public int FieldCount
{
get { return 3;//assuming the table has 3 columns }
}
public IDataReader GetData(int i)
{
if (i == 0)
return this;
return null;
}
public string GetDataTypeName(int i)
{
return "String";
}
public string GetName(int i)
{
return Values[i].ToString();
}
public string GetString(int i)
{
return Values[i].ToString();
}
public object GetValue(int i)
{
return Values[i];
}
public int GetValues(object[] values)
{
Fill(values);
Array.Copy(values, Values, this.FieldCount);
return this.FieldCount;
}
public object this[int i]
{
get { return Values[i]; }
}
Hope it helps.
It is not logical to have a DataSet as a member of System.Data.IDataReader.
Better think in terms of an XmlDocumnet, XDocument or an XmlReader.
This may help...
//1. Create dataset
var ds = new DataSet("A Dataset");
var table = ds.Tables.Add("A Table");
table.Columns.Add("Id", typeof(int));
table.Columns.Add("Description", typeof(string));
//2. Serialize as xml
ds.WriteXml(@"C:\temp\dataset.xml");
//3. Go look at the xml file's contents.
//Your xml needs to be translated into this schema.
//You will have to write this. (Boring transform work...)
//Dataset deserialization does not work with arbitrary xml documuents.
//4. Loading the xml file
var ds2 = new DataSet();
ds2.ReadXml(@"C:\temp\dataset.xml");
//Suggestion. Investigate using LINQ-to-xml. It would be easier to
//read the data from your xml schema. You could also load the Dataset tables row by row
//using this type of approach
//1. Load xml data into an XElement.
var element = XElement.Parse(@"<resultset>
<datarow>
<datacol>Row 1 - Col 1</datacol>
<datacol>Row 1 - Col 2</datacol>
<datacol>Row 1 - Col 3</datacol>
</datarow>
</resultset>
");
//2. Create a dataset
ds = new DataSet("A Dataset");
table = ds.Tables.Add("A Table");
table.Columns.Add("Col1", typeof(string));
table.Columns.Add("Col2", typeof(string));
table.Columns.Add("Col3", typeof(string));
//3. Walk XElements and add rows to tables
foreach (var row in element.Elements("datarow"))
{
var r = table.NewRow();
table.Rows.Add(r);
int i = 0;
foreach (var columnValue in row.Elements("datacol"))
{
r[i++] = columnValue.Value;
}
}
精彩评论