ページレポート/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; } } } |