ページレポート/RDLレポートでは、カスタムデータプロバイダを使用し、実行時と設計時に正規以外のデータソースを使用することができます。このチュートリアルでは、カスタムデータプロバイダを使用したプロジェクトのソリューションを作成し、CSVファイルからデータを取得する方法を紹介します。
このトピックでは、以下のタスクを行います。
このチュートリアルを完了すると、CSVファイルから取得したデータを読み込んだレポートがデザイナ上に表示されます。
カスタムデータプロバイダのためのデザイナプロジェクトを作成する
| テキスト(RichTextBoxのTextプロパティに貼り付けます) |
コードのコピー
|
|---|---|
1.レポートエクスプローラでは、データソースノードを右クリックし、[データソースの追加]を選択します。 2.[レポートデータソース]ダイアログでは、全般のページに2つの種類ボックスをドロップダウンし、CSV Data Providerを選択してOKをクリックします。 3.レポートエクスプローラで、DataSource1を右クリックし、[データセットの追加]を選択します。 4.表示されるダイアログでは、クエリのページを選択します。 5.クエリボックスをドロップダウンし、カスタムクエリエディタを表示します。 6.CSVファイルの選択ボタンをクリックし、このプロジェクトにCategories.csvファイルを開きます。 7.OKをクリックして設定を保存し、ダイアログを閉じます。 8.プレビューをクリックし、CSVから取得したデータのレポートを表示します。 |
|
Visual Basic
| Visual Basicコード(クラスの上貼り付けます) |
コードのコピー
|
|---|---|
Imports System.Xml Imports System.IO Imports GrapeCity.ActiveReports.Design |
|
C#
| C#コード(クラスの上貼り付けます) |
コードのコピー
|
|---|---|
using System.Xml; using System.IO; using GrapeCity.ActiveReports.Design; |
|
Visual Basic
| Visual Basicコード(Form_Loadイベント内に貼り付けます) |
コードのコピー
|
|---|---|
Using reportStream = File.OpenRead("DemoReport.rdlx")
Using reader = XmlReader.Create(reportStream)
Designer1.LoadReport(reader, DesignerReportType.Page)
End Using
End Using
|
|
C#
| C#コード(Form_Loadイベント内に貼り付けます) |
コードのコピー
|
|---|---|
using (var reportStream = File.OpenRead("DemoReport.rdlx"))
{
using (var reader = XmlReader.Create(reportStream))
{
designer1.LoadReport(reader, DesignerReportType.Page);
}
}
|
|
カスタムデータプロバイダを使用するためのプロジェクトを作成する
| Configファイルに貼り付けます |
コードのコピー
|
|---|---|
<?xml version="1.0" encoding="utf-8" ?>
<Configuration>
<Extensions>
<Data>
<Extension Name="CSV Custom" DisplayName="CSV Data Provider"
Type="CustomDataProvider.CSVDataProvider.CsvDataProviderFactory,
CustomDataProvider"
CommandTextEditorType="CustomDataProvider.CSVDataProvider.QueryEditor,
CustomDataProvider"/>
</Data>
</Extensions>
</Configuration>
|
|
| テキストファイルに貼り付けます |
コードのコピー
|
|---|---|
EmployeeID(int32),LastName,FirstName,Role,City 1,James,Yolanda,Owner,Columbus 7,Reed,Marvin,Manager,Newton 9,Figg,Murray,Cashier,Columbus 12,Snead,Lance,Store Keeper,Columbus 15,Halm,Jeffry,Store Keeper,Columbus 17,Hames,Alma,Store Keeper,Oak Bay 18,Nicki,Aubrey,Store Keeper,Columbus 24,Cliett,Vikki,Store Keeper,Newton |
|
データを表示するためのレポートを追加する
| テキストボックス名 | 値 | 背景色 |
|---|---|---|
| TextBox1 | 名前 | MediumSlateBlue |
| TextBox2 | 地位 | MediumSlateBlue |
| TextBox3 | 都市 | MediumSlateBlue |
| TextBox4 | =Fields!FirstName.Value & " " & Fields!LastName.Value | |
| TextBox5 | =Fields!Role.Value | |
| TextBox6 | =Fields!City.Value |
カスタムデータプロバイダを格納するためのクラスライブラリプロジェクトを追加する
Visual Basic
| Visual Basic コード(クラスのデフォルトスタブと置き換えます) |
コードのコピー
|
|---|---|
Namespace CSVDataProvider
'データソース内のフィールドに関する情報を表します。
Friend Structure CsvColumn
Private ReadOnly _fieldName As String
Private ReadOnly _dataType As Type
' CsvColumnクラスの新しいインスタンスを生成します。
' fieldNameはCsvColumnのインスタンスによって表されるフィールドの名前です。
' dataTypeはCsvColumnのインスタンスによって表されるフィールドの種類です。
Public Sub New(fieldName As String, dataType As Type)
If fieldName Is Nothing Then
Throw New ArgumentNullException("fieldName")
End If
If dataType Is Nothing Then
Throw New ArgumentNullException("dataType")
End If
_fieldName = fieldName
_dataType = dataType
End Sub
' CsvColumnのインスタンスによって表されるフィールドの名前を取得します。
Public ReadOnly Property FieldName() As String
Get
Return _fieldName
End Get
End Property
' CsvColumnのインスタンスによって表されるフィールドの種類を取得します。
Public ReadOnly Property DataType() As Type
Get
Return _dataType
End Get
End Property
' CsvColumnのインスタンスを表わす文字列を返します。
Public Overrides Function ToString() As String
Return [String].Concat(New String() {FieldName, "(", DataType.ToString(), ")"})
End Function
' 2つのCsvColumnのインスタンスが同じかどうかを判定します。
' 指定されたCsvColumnが現在のCsvColumnと同じである場合はTrueを返し、そうではない場合はFalseを返します。
Public Overrides Function Equals(obj As Object) As Boolean
Dim flag As Boolean
If TypeOf obj Is CsvColumn Then
flag = Equals(CType(obj, CsvColumn))
Else
flag = False
End If
Return flag
End Function
Private Overloads Function Equals(column As CsvColumn) As Boolean
Return column.FieldName = FieldName
End Function
' ハッシュテーブルのようなハッシュアルゴリズムやデータ構造での使用に適した、CsvColumnのハッシュ関数として機能します。
' 現在のCsvColumnインスタンスにハッシュコードを返します。
Public Overrides Function GetHashCode() As Integer
Return (FieldName.GetHashCode() + DataType.GetHashCode())
End Function
End Structure
End Namespace
|
|
C#
| C#コード(クラスのデフォルトスタブと置き換えます) |
コードのコピー
|
|---|---|
using System;
namespace CustomDataProvider.CSVDataProvider
{
// データソース内のフィールドに関する情報を表します。
internal struct CsvColumn
{
private readonly string _fieldName;
private readonly Type _dataType;
// CsvColumnクラスの新しいインスタンスを生成します。
// fieldNameはCsvColumnのインスタンスによって表されるフィールドの名前です。
// dataTypeはCsvColumnのインスタンスによって表されるフィールドの種類です。
public CsvColumn(string fieldName, Type dataType)
{
if (fieldName == null)
throw new ArgumentNullException("fieldName");
if (dataType == null)
throw new ArgumentNullException("dataType");
_fieldName = fieldName;
_dataType = dataType;
}
// CsvColumnのインスタンスによって表されるフィールドの名前を取得します。
public string FieldName
{
get { return _fieldName; }
}
//CsvColumnのインスタンスによって表されるフィールドの種類を取得します。
public Type DataType
{
get { return _dataType; }
}
//CsvColumnのインスタンスを表わす文字列を返します。
public override string ToString()
{
return String.Concat(new string[] {FieldName, "(", DataType.ToString(), ")"});
}
//2つのCsvColumnのインスタンスが同じかどうかを判定します。
//指定されたCsvColumnが現在のCsvColumnと同じである場合はTrueを返し、そうではない場合はFalseを返します。
public override bool Equals(object obj)
{
bool flag;
if (obj is CsvColumn)
{
flag = Equals((CsvColumn) obj);
}
else
{
flag = false;
}
return flag;
}
private bool Equals(CsvColumn column)
{
return column.FieldName == FieldName;
}
//ハッシュテーブルのようなハッシュアルゴリズムやデータ構造での使用に適した、CsvColumnのハッシュ関数として機能します。
//現在のCsvColumnインスタンスにハッシュコードを返します。
public override int GetHashCode()
{
return (FieldName.GetHashCode() + DataType.GetHashCode());
}
}
}
|
|
Visual Basic
| Visual Basicコード(クラスのデフォルトスタブと置き換えます) |
コードのコピー
|
|---|---|
Imports System.Text.RegularExpressions
Imports System.IO
Imports System.Globalization
Imports System.Data.Common
Namespace CSVDataProvider
''' <summary>
''' .NETフレームワークのCSVデータプロバイダの<see cref="DbDataReader"/>を実装する方法を提供します。
''' </summary>
Friend Class CsvDataReader
Inherits DbDataReader
Private _typeLookup As New Hashtable(New myCultureComparer(New CultureInfo("ja")))
Private _columnLookup As New Hashtable()
Private _columns As Object()
Private _textReader As TextReader
Private _currentRow As Object()
'早急な処理を行うために、正規表現をプリコンパイルします。
'マルチスレッドを避けるために、プロパティは読み取り専用に設定されています。
Private Shared ReadOnly _rxDataRow As New Regex(",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))", RegexOptions.Compiled)
'データ行を解析するために使用されます。
Private Shared ReadOnly _rxHeaderRow As New Regex("(?<fieldName>(\w*\s*)*)\((?<fieldType>\w*)\)", RegexOptions.Compiled)
'ヘッダ行を解析するために使用されます。
''' <summary>
''' </summary>
''' <param name="textReader">データ読み込みに使用される<see cref="TextReader"/>。</param>
Public Sub New(textReader As TextReader)
_textReader = textReader
ParseCommandText()
End Sub
''' <summary>
'''渡されたコマンドのテキストを解析します。
''' </summary>
Private Sub ParseCommandText()
If _textReader.Peek() = -1 Then
Return
End If
'コマンドのテキストは空であるか既に末尾にあります。
FillTypeLookup()
Try
If Not ParseHeader(_textReader.ReadLine()) Then
Throw New InvalidOperationException("フィールド名とデータ型が定義されていません。 CommandTextの先頭行には、フィールド名およびデータ型を追加する必要があります。例: FirstName(string)")
End If
Catch generatedExceptionName As Exception
End Try
End Sub
'ハッシュテーブルは、ヘッダのテキストで使用される文字列値の型を返すために使用されます。
Private Sub FillTypeLookup()
_typeLookup.Add("string", GetType([String]))
_typeLookup.Add("byte", GetType([Byte]))
_typeLookup.Add("boolean", GetType([Boolean]))
_typeLookup.Add("datetime", GetType(DateTime))
_typeLookup.Add("decimal", GetType([Decimal]))
_typeLookup.Add("double", GetType([Double]))
_typeLookup.Add("int16", GetType(Int16))
_typeLookup.Add("int32", GetType(Int32))
_typeLookup.Add("int", GetType(Int32))
_typeLookup.Add("integer", GetType(Int32))
_typeLookup.Add("int64", GetType(Int64))
_typeLookup.Add("sbyte", GetType([SByte]))
_typeLookup.Add("single", GetType([Single]))
_typeLookup.Add("time", GetType(DateTime))
_typeLookup.Add("date", GetType(DateTime))
_typeLookup.Add("uint16", GetType(UInt16))
_typeLookup.Add("uint32", GetType(UInt32))
_typeLookup.Add("uint64", GetType(UInt64))
End Sub
''' <summary>
''' ヘッダテキストの文字列から渡された文字列の値に基づいてデータ型を返します。一致しない場合は、文字列型が返されます。
''' </summary>
''' <param name="fieldType">ヘッダコマンドのテキスト文字列からの文字列値。</param>
Private Function GetFieldTypeFromString(fieldType As String) As Type
If _typeLookup.Contains(fieldType) Then
Return TryCast(_typeLookup(fieldType), Type)
End If
Return GetType([String])
End Function
''' <summary>
''' 渡されたコマンドのテキストの先頭行を解析し、フィールド名およびデータ型を作成します。フィールドの情報は、
''' <see cref="CsvColumn"/>構造体に保存され、列情報の項目はArrayListに格納されています。列名は、容易に検索できるハッシュテーブルに
''' 追加します。
''' </summary>
''' <param name="header">すべてのフィールドを含むヘッダ文字列。</param>
''' <returns>ヘッダ文字列を解析できる場合は、True。それ以外の場合は、False。</returns>
Private Function ParseHeader(header As String) As Boolean
Dim fieldName As String
Dim index As Integer = 0
If header.IndexOf("(") = -1 Then
Return False
End If
Dim matches As MatchCollection = _rxHeaderRow.Matches(header)
_columns = New Object(matches.Count - 1) {}
For Each match As Match In matches
fieldName = match.Groups("fieldName").Value
Dim fieldType As Type = GetFieldTypeFromString(match.Groups("fieldType").Value)
_columns.SetValue(New CsvColumn(fieldName, fieldType), index)
_columnLookup.Add(fieldName, index)
index += 1
Next
Return True
End Function
''' <summary>
''' 正規表現を使用し、データの行を解析します。データの現在の行となるオブジェクト配列内に情報を保存します。
''' 行でフィールド数が正しくない場合は、例外が発生します。
''' </summary>
''' <param name="dataRow">カンマ区切りのデータ行を表す文字列値。</param>
''' <returns>データ文字列を解析できる場合は、True。それ以外の場合は、False。</returns>
Private Function ParseDataRow(dataRow As String) As Boolean
Dim index As Integer = 0
Dim tempData As String() = _rxDataRow.Split(dataRow)
_currentRow = New Object(tempData.Length - 1) {}
If tempData.Length <> _columns.Length Then
Dim [error] As String = String.Format(CultureInfo.InvariantCulture, "無効な行: ""{0}""。 行ではテーブルヘッダの定義と同じデータ列が含まれていません。", dataRow)
Throw New InvalidOperationException([error])
End If
Dim i As Integer = 0
While i < tempData.Length
Dim value As String = tempData(i)
If value.Length > 1 Then
If value.IndexOf(""""c, 0) = 0 AndAlso value.IndexOf(""""c, 1) = value.Length - 1 Then
value = value.Substring(1, value.Length - 2)
End If
End If
_currentRow.SetValue(ConvertValue(GetFieldType(index), value), index)
index += 1
i += 1
End While
Return True
End Function
''' <summary>
'''フィールド型に基づいてコマンドのテキストからの文字列値を適切なデータ型に変換します。
''' また、String.EmptyまたはSystem.Data.DBNullを返す必要がないかを確認するためにいくつか文字列値のルールをチックします。
''' </summary>
''' <param name="type">現在の列の型は、データが属している.</param>
''' <param name="originalValue">コマンドテキストからの文字列値。</param>
''' <returns>データ型に基づいている変換された文字列を返します。</returns>
Private Function ConvertValue(type As Type, originalValue As String) As Object
Dim fieldType As Type = type
Dim invariantCulture As CultureInfo = CultureInfo.InvariantCulture
Try
If originalValue = """""" OrElse originalValue = " " Then
Return String.Empty
End If
If originalValue = "" Then
Return DBNull.Value
End If
If originalValue = "DBNull" Then
Return DBNull.Value
End If
If fieldType = GetType([String]) Then
Return originalValue.Trim()
End If
If fieldType = GetType(Int32) Then
Return Convert.ToInt32(originalValue, invariantCulture)
End If
If fieldType = GetType([Boolean]) Then
Return Convert.ToBoolean(originalValue, invariantCulture)
End If
If fieldType = GetType(DateTime) Then
Return Convert.ToDateTime(originalValue, invariantCulture)
End If
If fieldType = GetType([Decimal]) Then
Return Convert.ToDecimal(originalValue, invariantCulture)
End If
If fieldType = GetType([Double]) Then
Return Convert.ToDouble(originalValue, invariantCulture)
End If
If fieldType = GetType(Int16) Then
Return Convert.ToInt16(originalValue, invariantCulture)
End If
If fieldType = GetType(Int64) Then
Return Convert.ToInt64(originalValue, invariantCulture)
End If
If fieldType = GetType([Single]) Then
Return Convert.ToSingle(originalValue, invariantCulture)
End If
If fieldType = GetType([Byte]) Then
Return Convert.ToByte(originalValue, invariantCulture)
End If
If fieldType = GetType([SByte]) Then
Return Convert.ToSByte(originalValue, invariantCulture)
End If
If fieldType = GetType(UInt16) Then
Return Convert.ToUInt16(originalValue, invariantCulture)
End If
If fieldType = GetType(UInt32) Then
Return Convert.ToUInt32(originalValue, invariantCulture)
End If
If fieldType = GetType(UInt64) Then
Return Convert.ToUInt64(originalValue, invariantCulture)
End If
Catch e As Exception
Throw New InvalidOperationException(String.Format("入力値 '{0}'を'{1}'型に変換できません。", originalValue, type), e)
End Try
'一致しない場合は、DBNullを返します。
Return DBNull.Value
End Function
''' <summary>
''' <see cref="CsvDataReader"/>を次のレコードに移動します。
''' </summary>
''' <returns>他の行がある場合はTrue、それ以外の場合はFalse。</returns>
Public Overrides Function Read() As Boolean
If _textReader.Peek() > -1 Then
ParseDataRow(_textReader.ReadLine())
Else
Return False
End If
Return True
End Function
''' <summary>
'''<see cref="CsvDataReader"/>により使用されたリソースを解放します。
''' </summary>
Public Shadows Sub Dispose()
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
Protected Shadows Sub Dispose(disposing As Boolean)
If disposing Then
If _textReader IsNot Nothing Then
_textReader.Close()
End If
End If
_typeLookup = Nothing
_columnLookup = Nothing
_columns = Nothing
_currentRow = Nothing
End Sub
''' <summary>
''' Objectがガベージ コレクションにより収集される前に、その Object がリソースを解放し、その他のクリーンアップ操作を実行できるようにします。
''' </summary>
Protected Overrides Sub Finalize()
Try
Dispose(False)
Finally
MyBase.Finalize()
End Try
End Sub
''' <summary>
''' 現在の行の列数を取得します。
''' </summary>
Public Overrides ReadOnly Property FieldCount() As Integer
Get
If _columns Is Nothing Then
_columns = New Object(-1) {}
End If
Return _columns.Length
End Get
End Property
Public Overrides ReadOnly Property Depth() As Integer
Get
Return 0
End Get
End Property
Public Overrides ReadOnly Property IsClosed() As Boolean
Get
Return False
End Get
End Property
Public Overrides ReadOnly Property RecordsAffected() As Integer
Get
Return 0
End Get
End Property
Default Public Overrides ReadOnly Property Item(name As String) As Object
Get
Return Me(GetOrdinal(name).ToString())
End Get
End Property
Default Public Overrides ReadOnly Property Item(i As Integer) As Object
Get
Return GetValue(i)
End Get
End Property
Public Overrides ReadOnly Property HasRows As Boolean
Get
Throw New NotImplementedException()
End Get
End Property
''' <summary>
''' 指定したフィールドの値を返します。
''' </summary>
''' <param name="ordinal">検索するフィールドのインデックス。 </param>
''' <returns>フィールドの値を返す<see cref="Object"/>。</returns>
Public Overrides Function GetFieldType(ordinal As Integer) As Type
If ordinal > _columns.Length - 1 Then
Return Nothing
End If
Return CType(_columns.GetValue(ordinal), CsvColumn).DataType
End Function
''' <summary>
''' 指定したフィールドの値を返します。
''' </summary>
''' <param name="i">検索するフィールドのインデックス。 </param>
'''フィールドの名前を返します。値はない場合は、空の文字列("")を返します。
Public Overrides Function GetName(i As Integer) As String
If i > _columns.Length - 1 Then
Return String.Empty
End If
Return CType(_columns.GetValue(i), CsvColumn).FieldName
End Function
Public Overrides Function GetOrdinal(name As String) As Integer
Dim value As Object = _columnLookup(name)
If value Is Nothing Then
Throw New IndexOutOfRangeException("name")
End If
Return CType(value, Integer)
End Function
''' <summary>
''' 指定したフィールドの値を返します。
''' </summary>
''' <param name="i">検索するフィールドのインデックス。 </param>
''' <returns>フィールドの値を返す<see cref="Object"/>。</returns>
Public Overrides Function GetValue(i As Integer) As Object
If i > _columns.Length - 1 Then
Return Nothing
End If
Return _currentRow.GetValue(i)
End Function
Public Overrides Sub Close()
End Sub
Public Overrides Function GetSchemaTable() As System.Data.DataTable
Throw New NotImplementedException()
End Function
Public Overrides Function NextResult() As Boolean
Throw New NotImplementedException()
End Function
Public Overrides Function GetDataTypeName(i As Integer) As String
Return GetFieldType(i).ToString()
End Function
Public Overrides Function GetValues(values As Object()) As Integer
Throw New NotImplementedException()
End Function
Public Overrides Function GetBoolean(i As Integer) As Boolean
Throw New NotImplementedException()
End Function
Public Overrides Function GetByte(i As Integer) As Byte
Throw New NotImplementedException()
End Function
Public Overrides Function GetBytes(i As Integer, fieldOffset As Long, buffer As Byte(), bufferoffset As Integer, length As Integer) As Long
Throw New NotImplementedException()
End Function
Public Overrides Function GetChar(i As Integer) As Char
Throw New NotImplementedException()
End Function
Public Overrides Function GetChars(i As Integer, fieldoffset As Long, buffer As Char(), bufferoffset As Integer, length As Integer) As Long
Throw New NotImplementedException()
End Function
Public Overrides Function GetGuid(i As Integer) As Guid
Throw New NotImplementedException()
End Function
Public Overrides Function GetInt16(i As Integer) As Short
Throw New NotImplementedException()
End Function
Public Overrides Function GetInt32(i As Integer) As Integer
Throw New NotImplementedException()
End Function
Public Overrides Function GetInt64(i As Integer) As Long
Throw New NotImplementedException()
End Function
Public Overrides Function GetFloat(i As Integer) As Single
Throw New NotImplementedException()
End Function
Public Overrides Function GetDouble(i As Integer) As Double
Throw New NotImplementedException()
End Function
Public Overrides Function GetString(i As Integer) As String
Throw New NotImplementedException()
End Function
Public Overrides Function GetDecimal(i As Integer) As Decimal
Throw New NotImplementedException()
End Function
Public Overrides Function GetDateTime(i As Integer) As DateTime
Throw New NotImplementedException()
End Function
Public Overrides Function IsDBNull(i As Integer) As Boolean
Throw New NotImplementedException()
End Function
Public Overrides Function GetEnumerator() As IEnumerator
Throw New NotImplementedException()
End Function
#Region "EqualityComparer"
Private Class myCultureComparer
Implements IEqualityComparer
Public myComparer As CaseInsensitiveComparer
Public Sub New()
myComparer = CaseInsensitiveComparer.DefaultInvariant
End Sub
Public Sub New(myCulture As CultureInfo)
myComparer = New CaseInsensitiveComparer(myCulture)
End Sub
Public Shadows Function Equals(x As Object, y As Object) As Boolean Implements IEqualityComparer.Equals
If myComparer.Compare(x, y) = 0 Then
Return True
Else
Return False
End If
End Function
Public Shadows Function GetHashCode(obj As Object) As Integer Implements IEqualityComparer.GetHashCode
Return obj.ToString().ToLower().GetHashCode()
End Function
End Class
#End Region
End Class
End Namespace
|
|
C#
| C#コード(クラスのデフォルトスタブと置き換えます) |
コードのコピー
|
|---|---|
using System;
using System.Collections;
using System.Data.Common;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;
namespace CustomDataProvider.CSVDataProvider
{
/// <summary>
/// .NETフレームワークのCSVデータプロバイダの<see cref="DbDataReader"/>を実装する方法を提供します。
/// </summary>
internal class CsvDataReader : DbDataReader
{
private Hashtable _typeLookup = new Hashtable(new myCultureComparer(new CultureInfo("ja")));
private Hashtable _columnLookup = new Hashtable();
private object[] _columns;
private TextReader _textReader;
private object[] _currentRow;
//早急な処理を行うために、正規表現をプリコンパイルします。
//マルチスレッドを避けるために、プロパティは読み取り専用に設定されています。
private static readonly Regex _rxDataRow = new Regex(@",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))", RegexOptions.Compiled);
//データ行を解析するために使用されます。
private static readonly Regex _rxHeaderRow =
new Regex(@"(?<fieldName>(\w*\s*)*)\((?<fieldType>\w*)\)", RegexOptions.Compiled); //ヘッダ行を解析するために使用されます。
/// <summary>
/// </summary>
/// <param name="textReader">データ読み込みに使用される<see cref="TextReader"/>。</param>
public CsvDataReader(TextReader textReader)
{
_textReader = textReader;
ParseCommandText();
}
/// <summary>
///渡されたコマンドのテキストを解析します。
/// </summary>
private void ParseCommandText()
{
if (_textReader.Peek() == -1)
return; //コマンドのテキストは空であるか既に末尾にあります。
FillTypeLookup();
try
{
if (!ParseHeader(_textReader.ReadLine()))
throw new InvalidOperationException("フィールド名とデータ型が定義されていません。 CommandTextの先頭行には、フィールド名およびデータ型を追加する必要があります。例: FirstName(string)");
}
catch (Exception)
{
}
}
//ハッシュテーブルは、ヘッダのテキストで使用される文字列値の型を返すために使用されます。
private void FillTypeLookup()
{
_typeLookup.Add("string", typeof(String));
_typeLookup.Add("byte", typeof(Byte));
_typeLookup.Add("boolean", typeof(Boolean));
_typeLookup.Add("datetime", typeof(DateTime));
_typeLookup.Add("decimal", typeof(Decimal));
_typeLookup.Add("double", typeof(Double));
_typeLookup.Add("int16", typeof(Int16));
_typeLookup.Add("int32", typeof(Int32));
_typeLookup.Add("int", typeof(Int32));
_typeLookup.Add("integer", typeof(Int32));
_typeLookup.Add("int64", typeof(Int64));
_typeLookup.Add("sbyte", typeof(SByte));
_typeLookup.Add("single", typeof(Single));
_typeLookup.Add("time", typeof(DateTime));
_typeLookup.Add("date", typeof(DateTime));
_typeLookup.Add("uint16", typeof(UInt16));
_typeLookup.Add("uint32", typeof(UInt32));
_typeLookup.Add("uint64", typeof(UInt64));
}
/// <summary>
/// ヘッダテキストの文字列から渡された文字列の値に基づいてデータ型を返します。一致しない場合は、文字列型が返されます。
/// </summary>
/// <param name="fieldType">ヘッダコマンドのテキスト文字列からの文字列値。</param>
private Type GetFieldTypeFromString(string fieldType)
{
if (_typeLookup.Contains(fieldType))
return _typeLookup[fieldType] as Type;
return typeof(String);
}
/// <summary>
/// 渡されたコマンドのテキストの先頭行を解析し、フィールド名およびデータ型を作成します。フィールドの情報は、
/// <see cref="CsvColumn"/>構造体に保存され、列情報の項目はArrayListに格納されています。列名は、容易に検索できるハッシュテーブルに
/// 追加します。
/// </summary>
/// <param name="header">すべてのフィールドを含むヘッダ文字列。</param>
/// <returns>ヘッダ文字列を解析できる場合は、True。それ以外の場合は、False。</returns>
private bool ParseHeader(string header)
{
string fieldName;
int index = 0;
if (header.IndexOf("(") == -1)
{
return false;
}
MatchCollection matches = _rxHeaderRow.Matches(header);
_columns = new object[matches.Count];
foreach (Match match in matches)
{
fieldName = match.Groups["fieldName"].Value;
Type fieldType = GetFieldTypeFromString(match.Groups["fieldType"].Value);
_columns.SetValue(new CsvColumn(fieldName, fieldType), index);
_columnLookup.Add(fieldName, index);
index++;
}
return true;
}
/// <summary>
/// 正規表現を使用し、データの行を解析します。データの現在の行となるオブジェクト配列内に情報を保存します。
/// 行でフィールド数が正しくない場合は、例外が発生します。
/// </summary>
/// <param name="dataRow">カンマ区切りのデータ行を表す文字列値。</param>
/// <returns>データ文字列を解析できる場合は、True。それ以外の場合は、False。</returns>
private bool ParseDataRow(string dataRow)
{
int index = 0;
string[] tempData = _rxDataRow.Split(dataRow);
_currentRow = new object[tempData.Length];
if (tempData.Length != _columns.Length)
{
string error = string.Format(CultureInfo.InvariantCulture, "無効な行:\"{0}\"。 行ではテーブルヘッダの定義と同じデータ列が含まれていません。", dataRow);
throw new InvalidOperationException(error);
}
for (int i = 0; i < tempData.Length; i++)
{
string value = tempData[i];
if (value.Length > 1)
{
if (value.IndexOf('"', 0) == 0 && value.IndexOf('"', 1) == value.Length - 1)
value = value.Substring(1, value.Length - 2);
}
_currentRow.SetValue(ConvertValue(GetFieldType(index), value), index);
index++;
}
return true;
}
/// <summary>
///フィールド型に基づいてコマンドのテキストからの文字列値を適切なデータ型に変換します。
/// また、String.EmptyまたはSystem.Data.DBNullを返す必要がないかを確認するためにいくつか文字列値のルールをチックします。
/// </summary>
/// <param name="type">現在の列の型は、データが属している.</param>
/// <param name="originalValue">コマンドテキストからの文字列値。</param>
/// <returns>データ型に基づいている変換された文字列を返します。</returns>
private object ConvertValue(Type type, string originalValue)
{
Type fieldType = type;
CultureInfo invariantCulture = CultureInfo.InvariantCulture;
try
{
if (originalValue == "\"\"" || originalValue == " ")
return string.Empty;
if (originalValue == "")
return DBNull.Value;
if (originalValue == "DBNull")
return DBNull.Value;
if (fieldType == typeof(String))
return originalValue.Trim();
if (fieldType == typeof(Int32))
return Convert.ToInt32(originalValue, invariantCulture);
if (fieldType == typeof(Boolean))
return Convert.ToBoolean(originalValue, invariantCulture);
if (fieldType == typeof(DateTime))
return Convert.ToDateTime(originalValue, invariantCulture);
if (fieldType == typeof(Decimal))
return Convert.ToDecimal(originalValue, invariantCulture);
if (fieldType == typeof(Double))
return Convert.ToDouble(originalValue, invariantCulture);
if (fieldType == typeof(Int16))
return Convert.ToInt16(originalValue, invariantCulture);
if (fieldType == typeof(Int64))
return Convert.ToInt64(originalValue, invariantCulture);
if (fieldType == typeof(Single))
return Convert.ToSingle(originalValue, invariantCulture);
if (fieldType == typeof(Byte))
return Convert.ToByte(originalValue, invariantCulture);
if (fieldType == typeof(SByte))
return Convert.ToSByte(originalValue, invariantCulture);
if (fieldType == typeof(UInt16))
return Convert.ToUInt16(originalValue, invariantCulture);
if (fieldType == typeof(UInt32))
return Convert.ToUInt32(originalValue, invariantCulture);
if (fieldType == typeof(UInt64))
return Convert.ToUInt64(originalValue, invariantCulture);
}
catch (Exception e)
{
throw new InvalidOperationException(string.Format("入力値 \'{0}\'を\'{1}\'型に変換できません。", originalValue, type), e);
}
//一致しない場合は、DBNullを返します。
return DBNull.Value;
}
/// <summary>
/// <see cref="CsvDataReader"/>を次のレコードに移動します。
/// </summary>
/// <returns>他の行がある場合はTrue、それ以外の場合はFalse。</returns>
public override bool Read()
{
if (_textReader.Peek() > -1)
ParseDataRow(_textReader.ReadLine());
else
return false;
return true;
}
/// <summary>
///<see cref="CsvDataReader"/>により使用されたリソースを解放します。
/// </summary>
public new void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (_textReader != null)
_textReader.Close();
}
_typeLookup = null;
_columnLookup = null;
_columns = null;
_currentRow = null;
}
/// <summary>
/// Objectがガベージ コレクションにより収集される前に、その Object がリソースを解放し、その他のクリーンアップ操作を実行できるようにします。
/// </summary>
~CsvDataReader()
{
Dispose(false);
}
/// <summary>
/// 現在の行の列数を取得します。
/// </summary>
public override int FieldCount
{
get
{
if (_columns == null)
_columns = new object[0];
return _columns.Length;
}
}
public override int Depth
{
get { return 0; }
}
public override bool IsClosed
{
get { return false; }
}
public override int RecordsAffected
{
get { return 0; }
}
public override bool HasRows
{
get
{
throw new NotImplementedException();
}
}
public override object this[string name]
{
get { return this[GetOrdinal(name).ToString()]; }
}
public override object this[int i]
{
get { return GetValue(i); }
}
/// <summary>
/// 指定したフィールドの値を返します。
/// </summary>
/// <param name="i">検索するフィールドのインデックス。 </param>
/// <returns>フィールドの値を返す<see cref="Object"/>。</returns>
public override Type GetFieldType(int ordinal)
{
if (ordinal > _columns.Length - 1)
return null;
return ((CsvColumn)_columns.GetValue(ordinal)).DataType;
}
/// <summary>
/// 指定したフィールドの値を返します。
/// </summary>
/// <param name="i">検索するフィールドのインデックス。 </param>
///フィールドの名前を返します。値はない場合は、空の文字列("")を返します。
public override string GetName(int i)
{
if (i > _columns.Length - 1)
return string.Empty;
return ((CsvColumn)_columns.GetValue(i)).FieldName;
}
public override int GetOrdinal(string name)
{
object value = _columnLookup[name];
if (value == null)
throw new IndexOutOfRangeException("name");
return (int)value;
}
/// <summary>
/// 指定したフィールドの値を返します。
/// </summary>
/// <param name="i">検索するフィールドのインデックス。 </param>
/// <returns>フィールドの値を返す<see cref="Object"/>。</returns>
public override object GetValue(int i)
{
if (i > _columns.Length - 1)
return null;
return _currentRow.GetValue(i);
}
public override void Close()
{ }
public override System.Data.DataTable GetSchemaTable()
{
throw new NotImplementedException();
}
public override bool NextResult()
{
throw new NotImplementedException();
}
public override string GetDataTypeName(int i)
{
return GetFieldType(i).ToString();
}
public override int GetValues(object[] values)
{
throw new NotImplementedException();
}
public override bool GetBoolean(int i)
{
throw new NotImplementedException();
}
public override byte GetByte(int i)
{
throw new NotImplementedException();
}
public override long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
{
throw new NotImplementedException();
}
public override char GetChar(int i)
{
throw new NotImplementedException();
}
public override long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
{
throw new NotImplementedException();
}
public override Guid GetGuid(int i)
{
throw new NotImplementedException();
}
public override short GetInt16(int i)
{
throw new NotImplementedException();
}
public override int GetInt32(int i)
{
throw new NotImplementedException();
}
public override long GetInt64(int i)
{
throw new NotImplementedException();
}
public override float GetFloat(int i)
{
throw new NotImplementedException();
}
public override double GetDouble(int i)
{
throw new NotImplementedException();
}
public override string GetString(int i)
{
throw new NotImplementedException();
}
public override decimal GetDecimal(int i)
{
throw new NotImplementedException();
}
public override DateTime GetDateTime(int i)
{
throw new NotImplementedException();
}
public override bool IsDBNull(int i)
{
throw new NotImplementedException();
}
public override IEnumerator GetEnumerator()
{
throw new NotImplementedException();
}
#region EqualityComparer
class myCultureComparer : IEqualityComparer
{
public CaseInsensitiveComparer myComparer;
public myCultureComparer()
{
myComparer = CaseInsensitiveComparer.DefaultInvariant;
}
public myCultureComparer(CultureInfo myCulture)
{
myComparer = new CaseInsensitiveComparer(myCulture);
}
public new bool Equals(object x, object y)
{
if (myComparer.Compare(x, y) == 0)
{
return true;
}
else
{
return false;
}
}
public int GetHashCode(object obj)
{
return obj.ToString().ToLower().GetHashCode();
}
}
#endregion
}
}
|
|
Visual Basic
| Visual Basicコード(クラスのデフォルトスタブと置き換えます) |
コードのコピー
|
|---|---|
Imports System.IO
Imports System.Data.Common
Namespace CSVDataProvider
''' <summary>
'''.NETフレームワークのCSVデータプロバイダの<see cref="DbCommand"/>を実装する方法を提供します。
''' </summary>
Public NotInheritable Class CsvCommand
Inherits DbCommand
Private _commandText As String
Private _connection As DbConnection
Private _commandTimeout As Integer
Private _commandType As CommandType
''' <summary>
''' <see cref="CsvCommand"/>クラスの新しいインスタンスを作成します。
''' </summary>
Public Sub New()
Me.New(String.Empty)
End Sub
''' <summary>
''' コマンドのテキストとともに<see cref="CsvCommand"/>クラスの新しいインスタンスを作成します。
''' </summary>
''' <param name="commandText">コマンドのテキスト。</param>
Public Sub New(commandText As String)
Me.New(commandText, Nothing)
End Sub
''' <summary>
''' コマンドのテキストとともに<see cref="CsvCommand"/>クラスの新しいインスタンスを作成します。<see cref="CsvConnection"/>.
''' </summary>
''' <param name="commandText">コマンドのテキスト。</param>>
''' <param name="connection">データソースへの接続を表す<see cref="CsvConnection"/>。</param>
Public Sub New(commandText As String, connection As CsvConnection)
_commandText = commandText
_connection = connection
End Sub
''' <summary>
''' データソースで実行するコマンドを取得または設定します。
''' </summary>
Public Overrides Property CommandText() As String
Get
Return _commandText
End Get
Set
_commandText = Value
End Set
End Property
''' <summary>
''' コマンドの実行を終了して、エラーを生成するまでの待機時間を取得または設定します。
''' </summary>
Public Overrides Property CommandTimeout() As Integer
Get
Return _commandTimeout
End Get
Set
_commandTimeout = Value
End Set
End Property
''' <summary>
''' <see cref="CommandText"/>プロパティの解釈方法を示す値を取得または設定します。
''' </summary>
''' <remarks>We don't use it for Csv Data Provider.</remarks>
Public Overrides Property CommandType() As CommandType
Get
Return _commandType
End Get
Set
_commandType = Value
End Set
End Property
''' <summary>
''' <see cref="CsvConnection"/>に<see cref="CommandText"/>を送信し、<see cref="CommandBehavior"/>の1つの値を使用し、<see cref="CsvDataReader"/>を作成します。
''' </summary>
''' <param name="behavior"><see cref="CommandBehavior"/>値の1つ。</param>
''' <returns><see cref="CsvDataReader"/>のオブジェクト。</returns>
Protected Overrides Function ExecuteDbDataReader(behavior As CommandBehavior) As DbDataReader
Return New CsvDataReader(New StringReader(_commandText))
End Function
''' <summary>
'''定数に拡張されたパラメータを持つコマンドのテキストを返します。
''' </summary>
''' <returns>定数に拡張されたパラメータを持つコマンドのテキストを表す文字列。</returns>
Public Function GenerateRewrittenCommandText() As String
Return _commandText
End Function
''' <summary>
''' <see cref="CsvConnection"/>に<see cref="CommandText"/>を送信し、<see cref="CsvDataReader"/>を作成します。
''' </summary>
''' <returns><see cref="CsvDataReader"/>のオブジェクト。</returns>
Public Shadows Function ExecuteReader() As IDataReader
Return MyBase.ExecuteReader(CommandBehavior.SchemaOnly)
End Function
Public Overrides Property UpdatedRowSource() As UpdateRowSource
Get
Return UpdateRowSource.None
End Get
Set
End Set
End Property
Protected Overrides Property DbConnection As DbConnection
Get
Return _connection
End Get
Set(value As DbConnection)
_connection = value
End Set
End Property
Protected Overrides ReadOnly Property DbParameterCollection As DbParameterCollection
Get
Throw New NotImplementedException()
End Get
End Property
Protected Overrides Property DbTransaction As DbTransaction
Get
Throw New NotImplementedException()
End Get
Set(value As DbTransaction)
Throw New NotImplementedException()
End Set
End Property
Public Overrides Property DesignTimeVisible As Boolean
Get
Throw New NotImplementedException()
End Get
Set(value As Boolean)
Throw New NotImplementedException()
End Set
End Property
Public Overrides Sub Cancel()
'do nothing
End Sub
Public Shadows Function CreateParameter() As IDbDataParameter
'do nothing
Return Nothing
End Function
''' <summary>
''' <see cref="CsvCommand"/>により使用されたリソースを解放します。
''' </summary>
Public Shadows Sub Dispose()
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
Protected Shadows Sub Dispose(disposing As Boolean)
If disposing Then
If _connection IsNot Nothing Then
_connection.Dispose()
_connection = Nothing
End If
End If
End Sub
Public Overrides Sub Prepare()
'do nothing
End Sub
Public Overrides Function ExecuteNonQuery() As Integer
Return 0
End Function
Public Overrides Function ExecuteScalar() As Object
'do nothing
Return Nothing
End Function
Protected Overrides Function CreateDbParameter() As DbParameter
Throw New NotImplementedException()
End Function
End Class
End Namespace
|
|
C#
| C# コード(クラスのデフォルトスタブと置き換えます) |
コードのコピー
|
|---|---|
using System;
using System.Data;
using System.Data.Common;
using System.IO;
namespace CustomDataProvider.CSVDataProvider
{
/// <summary>
///.NETフレームワークのCSVデータプロバイダの<see cref="IDbCommand"/>を実装する方法を提供します。
/// </summary>
public sealed class CsvCommand : DbCommand
{
private string _commandText;
private DbConnection _connection;
private int _commandTimeout;
private CommandType _commandType;
/// <summary>
/// <see cref="CsvCommand"/>クラスの新しいインスタンスを作成します。
/// </summary>
public CsvCommand()
: this(string.Empty)
{
}
/// <summary>
/// コマンドのテキストとともに<see cref="CsvCommand"/>クラスの新しいインスタンスを作成します。
/// </summary>
/// <param name="commandText">コマンドのテキスト。</param>
public CsvCommand(string commandText)
: this(commandText, null)
{
}
/// <summary>
/// コマンドのテキストとともに<see cref="CsvCommand"/>クラスの新しいインスタンスを作成します。<see cref="CsvConnection"/>.
/// </summary>
/// <param name="commandText">コマンドのテキスト。</ PARAM>
/// <param name="connection">データソースへの接続を表す<see cref="CsvConnection"/>。</ PARAM>
public CsvCommand(string commandText, CsvConnection connection)
{
_commandText = commandText;
_connection = connection;
}
/// <summary>
/// データソースで実行するコマンドを取得または設定します。
/// </summary>
public override string CommandText
{
get { return _commandText; }
set { _commandText = value; }
}
/// <summary>
/// コマンドの実行を終了して、エラーを生成するまでの待機時間を取得または設定します。
/// </summary>
public override int CommandTimeout
{
get { return _commandTimeout; }
set { _commandTimeout = value; }
}
/// <summary>
/// <see cref="CommandText"/>プロパティの解釈方法を示す値を取得または設定します。
/// </summary>
/// <remarks>We don't use it for Csv Data Provider.</remarks>
public override CommandType CommandType
{
get { return _commandType; }
set { _commandType = value; }
}
/// <summary>
/// <see cref="CsvConnection"/>に<see cref="CommandText"/>を送信し、<see cref="CommandBehavior"/>の1つの値を使用し、<see cref="CsvDataReader"/>を作成します。
/// </summary>
/// <param name="behavior"><see cref="CommandBehavior"/>値の1つ。</param>
/// <returns><see cref="CsvDataReader"/>のオブジェクト。</returns>
protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior)
{
return new CsvDataReader(new StringReader(_commandText));
}
/// <summary>
///定数に拡張されたパラメータを持つコマンドのテキストを返します。
/// </summary>
/// <returns>定数に拡張されたパラメータを持つコマンドのテキストを表す文字列。</returns>
public string GenerateRewrittenCommandText()
{
return _commandText;
}
/// <summary>
/// <see cref="CsvConnection"/>に<see cref="CommandText"/>を送信し、<see cref="CsvDataReader"/>を作成します。
/// </summary>
/// <returns><see cref="CsvDataReader"/>のオブジェクト。</returns>
public new IDataReader ExecuteReader()
{
return ExecuteReader(CommandBehavior.SchemaOnly);
}
public override UpdateRowSource UpdatedRowSource
{
get { return UpdateRowSource.None; }
set { }
}
protected override DbConnection DbConnection
{
get { return _connection; }
set { _connection = value; }
}
protected override DbParameterCollection DbParameterCollection
{
get
{
throw new NotImplementedException();
}
}
protected override DbTransaction DbTransaction
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public override bool DesignTimeVisible
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public override void Cancel()
{
//do nothing
}
public new IDbDataParameter CreateParameter()
{
//do nothing
return null;
}
/// <summary>
/// <see cref="CsvCommand"/>により使用されたリソースを解放します。
/// </summary>
public new void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (_connection != null)
{
_connection.Dispose();
_connection = null;
}
}
}
public override void Prepare()
{
//do nothing
}
public override int ExecuteNonQuery()
{
return 0;
}
public override object ExecuteScalar()
{
//do nothing
return null;
}
protected override DbParameter CreateDbParameter()
{
throw new NotImplementedException();
}
}
}
|
|
Visual Basic
| Visual Basicコード(クラスのデフォルトスタブと置き換えます) |
コードのコピー
|
|---|---|
Imports System.Data.Common
Imports System.Data
Imports System.Collections.Specialized
Imports System
Namespace CSVDataProvider
''' <summary>
''' .NETフレームワークのCSVデータプロバイダの<see cref="DbConnection"/>を実装する方法を提供します。
''' </summary>
Public NotInheritable Class CsvConnection
Inherits DbConnection
Private ReadOnly _localizedName As String
''' <summary>
''' <see cref="CsvConnection"/>クラスの新しいインスタンスを作成します。
''' </summary>
Public Sub New()
_localizedName = "Csv"
End Sub
''' <summary>
''' <see cref="CsvConnection"/>クラスの新しいインスタンスを作成します。
''' </summary>
'''<param name="localizeName"><see cref="CsvConnection"/>のインスタンスのローカライズされた名前。</param>
Public Sub New(localizeName As String)
_localizedName = localizeName
End Sub
''' <summary>
''' データソースへの接続を開くために使用される文字列を取得または設定します。
''' </summary>
''' <remarks>Csvデータプロバイダに対する使用されません。</remarks>
Public Overrides Property ConnectionString() As String
Get
Return String.Empty
End Get
Set
End Set
End Property
''' <summary>
''' 接続の実行を終了して、エラーを生成するまでの待機時間を取得します。
''' </summary>
''' <remarks>Csvデータプロバイダに対する使用されません。</remarks>
Public Overrides ReadOnly Property ConnectionTimeout() As Integer
Get
Throw New NotImplementedException()
End Get
End Property
''' <summary>
'''データソースのトランザクションを開始します。
''' </summary>
''' 新しいトランザクションを表すオブジェクト。
''' <remarks>Csvデータプロバイダに対する使用されません。</remarks>
Protected Overrides Function BeginDbTransaction(isolationLevel As IsolationLevel) As DbTransaction
Return Nothing
End Function
''' <summary>
''' データソース接続を開きます。
''' </summary>
''' <remarks>Csvデータプロバイダに対する使用されません。</remarks>
Public Overrides Sub Open()
End Sub
''' <summary>
''' データソースへの接続を閉じます。
''' </summary>
Public Overrides Sub Close()
Dispose()
End Sub
Protected Overrides Function CreateDbCommand() As DbCommand
Return New CsvCommand(String.Empty)
End Function
''' <summary>
'''<see cref="CsvCommand"/>により使用されたリソースを解放します。
''' </summary>
Public Shadows Sub Dispose()
MyBase.Dispose(True)
GC.SuppressFinalize(Me)
End Sub
''' <summary>
''' <see cref="CsvConnection"/>のローカライズされた名前を取得します。
''' </summary>
Public ReadOnly Property LocalizedName() As String
Get
Return _localizedName
End Get
End Property
Public Overrides ReadOnly Property State() As ConnectionState
Get
Return ConnectionState.Open
End Get
End Property
Public Overrides ReadOnly Property Database() As String
Get
Return String.Empty
End Get
End Property
Public Overrides ReadOnly Property DataSource() As String
Get
Throw New NotImplementedException()
End Get
End Property
Public Overrides ReadOnly Property ServerVersion() As String
Get
Throw New NotImplementedException()
End Get
End Property
''' <summary>
''' この拡張機能の構成情報を指定します。
''' </summary>
''' <param name="configurationSettings">この設定の<see cref="NameValueCollection"/>。</param>
Public Sub SetConfiguration(configurationSettings As NameValueCollection)
End Sub
Public Shadows Function BeginTransaction(il As IsolationLevel) As IDbTransaction
'do nothing
Return Nothing
End Function
Public Overrides Sub ChangeDatabase(databaseName As String)
'do nothing
End Sub
End Class
End Namespace
|
|
C#
| C#コード(デフォルトスタブと置換するには貼り付けます) |
コードのコピー
|
|---|---|
using System;
using System.Collections.Specialized;
using System.Data;
using System.Data.Common;
namespace CustomDataProvider.CSVDataProvider
{
/// <summary>
/// .NETフレームワークのCSVデータプロバイダの<see cref="DbConnection"/>を実装する方法を提供します。
/// </summary>
public sealed class CsvConnection : DbConnection
{
private readonly string _localizedName;
/// <summary>
/// <see cref="CsvConnection"/>クラスの新しいインスタンスを作成します。
/// </summary>
public CsvConnection()
{
_localizedName = "Csv";
}
/// <summary>
/// <see cref="CsvConnection"/>クラスの新しいインスタンスを作成します。
/// </summary>
///<param name="localizeName"><see cref="CsvConnection"/>のインスタンスのローカライズされた名前。</param>
public CsvConnection(string localizeName)
{
_localizedName = localizeName;
}
/// <summary>
/// データソースへの接続を開くために使用される文字列を取得または設定します。
/// </summary>
/// <remarks>Csvデータプロバイダに対する使用されません。</remarks>
public override string ConnectionString
{
get { return string.Empty; }
set { }
}
/// <summary>
/// 接続の実行を終了して、エラーを生成するまでの待機時間を取得します。
/// </summary>
/// <remarks>Csvデータプロバイダに対する使用されません。</remarks>
public override int ConnectionTimeout
{
get { throw new NotImplementedException(); }
}
/// <summary>
///データソースのトランザクションを開始します。
/// </summary>
/// 新しいトランザクションを表すオブジェクト。
/// <remarks>Csvデータプロバイダに対する使用されません。</remarks>
protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel)
{
return null;
}
/// <summary>
/// データソース接続を開きます。
/// </summary>
/// <remarks>Csvデータプロバイダに対する使用されません。</remarks>
public override void Open()
{
}
/// <summary>
/// データソースへの接続を閉じます。
/// </summary>
public override void Close()
{
Dispose();
}
protected override DbCommand CreateDbCommand()
{
return new CsvCommand(string.Empty);
}
/// <summary>
///<see cref="CsvCommand"/>により使用されたリソースを解放します。
/// </summary>
public new void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// <see cref="CsvConnection"/>のローカライズされた名前を取得します。
/// </summary>
public string LocalizedName
{
get { return _localizedName; }
}
public override ConnectionState State
{
get { return ConnectionState.Open; }
}
public override string Database
{
get
{
return string.Empty;
}
}
public override string DataSource
{
get
{
throw new NotImplementedException();
}
}
public override string ServerVersion
{
get
{
throw new NotImplementedException();
}
}
/// <summary>
/// この拡張機能の構成情報を指定します。
/// </summary>
/// <param name="configurationSettings">この設定の<see cref="NameValueCollection"/>。</param>
public void SetConfiguration(NameValueCollection configurationSettings)
{
}
public new IDbTransaction BeginTransaction(IsolationLevel il)
{
//do nothing
return null;
}
public override void ChangeDatabase(string databaseName)
{
//do nothing
}
}
}
|
|
Visual Basic
| Visual Basicコード(クラスのデフォルトスタブと置き換えます) |
コードのコピー
|
|---|---|
Imports System.Data.Common
Namespace CSVDataProvider
''' <summary>
''' .NETフレームワークのCSVデータプロバイダの<see cref="DbProviderFactory"/>を実装する方法を提供します。
''' </summary>
Public Class CsvDataProviderFactory
Inherits DbProviderFactory
''' <summary>
''' <see cref="CsvCommand"/>の新しいインスタンスを返します。
''' </summary>
Public Overrides Function CreateCommand() As DbCommand
Return New CsvCommand()
End Function
''' <summary>
''' <see cref="CsvConnection"/>の新しいインスタンスを返します。
''' </summary>
Public Overrides Function CreateConnection() As DbConnection
Return New CsvConnection()
End Function
End Class
End Namespace
|
|
C#
| C#コード(クラスのデフォルトスタブと置き換えます) |
コードのコピー
|
|---|---|
using System.Data.Common;
namespace CustomDataProvider.CSVDataProvider
{
/// <summary>
/// .NETフレームワークのCSVデータプロバイダの<see cref="DbProviderFactory"/>を実装する方法を提供します。
/// </summary>
public class CsvDataProviderFactory : DbProviderFactory
{
/// <summary>
/// <see cref="CsvCommand"/>の新しいインスタンスを返します。
/// </summary>
public override DbCommand CreateCommand()
{
return new CsvCommand();
}
/// <summary>
/// <see cref="CsvConnection"/>の新しいインスタンスを返します。
/// </summary>
public override DbConnection CreateConnection()
{
return new CsvConnection();
}
}
}
|
|
クエリエディタにボタンを追加する
Visual Basic
| Visual Basicコード(クラスのデフォールトスタブと置き換えます) |
コードのコピー
|
|---|---|
Imports System Imports System.Collections.Generic Imports System.Drawing.Design Imports System.IO Imports System.Linq Imports System.Text Imports System.Text.RegularExpressions Imports System.Windows.Forms Imports System.Windows.Forms.Design
Namespace CSVDataProvider
Public NotInheritable Class QueryEditor
Inherits UITypeEditor
Dim path = ""
Friend WithEvents btn As New Button()
Public Overrides Function GetEditStyle(context As System.ComponentModel.ITypeDescriptorContext) As UITypeEditorEditStyle
Return UITypeEditorEditStyle.DropDown
End Function
Public Overrides Function EditValue(context As System.ComponentModel.ITypeDescriptorContext, provider As System.IServiceProvider, value As Object) As Object
Dim edSvc As IWindowsFormsEditorService = DirectCast(provider.GetService(GetType(IWindowsFormsEditorService)), IWindowsFormsEditorService)
btn.Text = "Select CSV File..."
Dim pdg = btn.Padding
pdg.Bottom += 2
btn.Padding = pdg
edSvc.DropDownControl(btn)
If String.IsNullOrEmpty(path) Then
Return String.Empty
End If
If Not File.Exists(path) Then
Return String.Empty
End If
Return GetCSVQuery(path)
End Function
Private Sub btn_Click(sender As System.Object, e As System.EventArgs) Handles btn.Click
Using openDlg = New OpenFileDialog()
openDlg.Filter = "CSV Files (*.csv)|*.csv|All Files (*.*)|*.*"
If openDlg.ShowDialog() <> DialogResult.OK Then
path = ""
Else
path = openDlg.FileName
End If
End Using
End Sub
Private Shared Function GetCSVQuery(ByVal csvFileName As String) As String
Dim sr As StreamReader = Nothing
Try
sr = New StreamReader(csvFileName)
Dim ret As String = String.Empty
Dim currentLine As String
Dim line As Integer = 0
currentLine = sr.ReadLine()
While (currentLine) IsNot Nothing
If (line).Equals(0) Then
ret += ProcessColumnsDefinition(currentLine) + vbCr & vbLf
Else
ret += currentLine + vbCr & vbLf
End If
line = line + 1
currentLine = sr.ReadLine()
End While
Return ret
Catch generatedExceptionName As IOException
Return String.Empty
Finally
If Not (sr) Is Nothing Then
sr.Close()
End If
End Try
End Function
Private Shared Function ProcessColumnsDefinition(ByVal line As String) As String
Const ColumnWithDataTypeRegex As String = "[""]?\w+[\""]?\(.+\)"
Dim columns As String() = line.Split(New String() {","}, StringSplitOptions.None)
Dim ret As String = Nothing
For Each column As String In columns
If Not String.IsNullOrEmpty(ret) Then
ret += ","
End If
If Not Regex.Match(column, ColumnWithDataTypeRegex).Success Then
ret += column + "(string)"
Else
ret += column
End If
Next
Return ret
End Function
End Class
End Namespace
|
|
C#
| C#コード(デフォールトスタブと置換するには貼り付けます) |
コードのコピー
|
|---|---|
using System;
using System.Collections.Generic;
using System.Drawing.Design;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Windows.Forms.Design;
namespace CustomDataProvider.CSVDataProvider
{
public sealed class QueryEditor : UITypeEditor
{
public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.DropDown;
}
public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, System.IServiceProvider provider, object value)
{
IWindowsFormsEditorService edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
var path = "";
var btn = new Button();
btn.Text = "Select CSV File...";
var pdg = btn.Padding;
pdg.Bottom += 2;
btn.Padding = pdg;
btn.Click += delegate
{
using (var openDlg = new OpenFileDialog())
{
openDlg.Filter = "CSV Files (*.csv)|*.csv|All Files (*.*)|*.*";
if (openDlg.ShowDialog() != DialogResult.OK)
path = "";
else
path = openDlg.FileName;
}
};
edSvc.DropDownControl(btn);
if (string.IsNullOrEmpty(path)) return string.Empty;
if (!File.Exists(path)) return string.Empty;
return GetCSVQuery(path);
}
/// <summary>
/// 指定したファイルの内容を読み込み、CSVデータプロバイダのクエリ文字列を作成します。
/// </summary>
/// <param name="csvFileName">CSVファイルの完全なパス。</param>
/// <returns>CSVデータプロバイダのクエリ文字列。</returns>
/// <remarks>
/// この方法は、ファイルの行を1つずつ読み込み、クエリ文字列に追加します。
/// CSVのクエリ文字列の先頭行には、列名と列のデータ型があるため、
///特有の処理を実行します。
/// </remarks>
private static string GetCSVQuery(string csvFileName)
{
StreamReader sr = null;
try
{
sr = new StreamReader(csvFileName);
string ret = string.Empty;
string currentLine;
int line = 0;
while ((currentLine = sr.ReadLine()) != null)
{
if (line == 0)
ret += ProcessColumnsDefinition(currentLine) + "\r\n";
else
ret += currentLine + "\r\n";
line++;
}
return ret;
}
catch (IOException)
{
return string.Empty;
}
finally
{
if (sr != null)
sr.Close();
}
}
/// <summary>
///指定した文字列からCSVデータの列の定義を読み込み、必要に応じて調整します。
/// </summary>
/// <param name="line">CSVデータの列の定義を含む文字列。</param>
/// <returns>データ型の定義を含むCSVデータ列の定義。</returns>
private static string ProcessColumnsDefinition(string line)
{
const string ColumnWithDataTypeRegex = @"[""]?\w+[\""]?\(.+\)";
string[] columns = line.Split(new string[] { "," }, StringSplitOptions.None);
string ret = null;
foreach (string column in columns)
{
if (!string.IsNullOrEmpty(ret))
ret += ",";
if (!Regex.Match(column, ColumnWithDataTypeRegex).Success)
{
ret += column + "(string)";
}
else
{
ret += column;
}
}
return ret;
}
}
}
|
|