1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.ComponentModel; 6 using System.ComponentModel.Design.Serialization; 7 using System.Diagnostics; 8 using System.Globalization; 9 using System.Reflection; 10 11 namespace System.Data.Common 12 { 13 [TypeConverter(typeof(DataColumnMappingConverter))] 14 public sealed class DataColumnMapping : MarshalByRefObject, IColumnMapping, ICloneable 15 { 16 private DataColumnMappingCollection _parent; 17 private string _dataSetColumnName; 18 private string _sourceColumnName; 19 DataColumnMapping()20 public DataColumnMapping() 21 { 22 } 23 DataColumnMapping(string sourceColumn, string dataSetColumn)24 public DataColumnMapping(string sourceColumn, string dataSetColumn) 25 { 26 SourceColumn = sourceColumn; 27 DataSetColumn = dataSetColumn; 28 } 29 30 [DefaultValue("")] 31 public string DataSetColumn 32 { 33 get { return _dataSetColumnName ?? string.Empty; } 34 set { _dataSetColumnName = value; } 35 } 36 37 internal DataColumnMappingCollection Parent 38 { 39 get 40 { 41 return _parent; 42 } 43 set 44 { 45 _parent = value; 46 } 47 } 48 49 [DefaultValue("")] 50 public string SourceColumn 51 { 52 get { return _sourceColumnName ?? string.Empty; } 53 set 54 { 55 if ((null != Parent) && (0 != ADP.SrcCompare(_sourceColumnName, value))) 56 { 57 Parent.ValidateSourceColumn(-1, value); 58 } 59 _sourceColumnName = value; 60 } 61 } 62 ICloneable.Clone()63 object ICloneable.Clone() 64 { 65 DataColumnMapping clone = new DataColumnMapping(); 66 clone._sourceColumnName = _sourceColumnName; 67 clone._dataSetColumnName = _dataSetColumnName; 68 return clone; 69 } 70 71 [EditorBrowsable(EditorBrowsableState.Advanced)] GetDataColumnBySchemaAction(DataTable dataTable, Type dataType, MissingSchemaAction schemaAction)72 public DataColumn GetDataColumnBySchemaAction(DataTable dataTable, Type dataType, MissingSchemaAction schemaAction) 73 { 74 return GetDataColumnBySchemaAction(SourceColumn, DataSetColumn, dataTable, dataType, schemaAction); 75 } 76 77 [EditorBrowsable(EditorBrowsableState.Advanced)] GetDataColumnBySchemaAction(string sourceColumn, string dataSetColumn, DataTable dataTable, Type dataType, MissingSchemaAction schemaAction)78 public static DataColumn GetDataColumnBySchemaAction(string sourceColumn, string dataSetColumn, DataTable dataTable, Type dataType, MissingSchemaAction schemaAction) 79 { 80 if (null == dataTable) 81 { 82 throw ADP.ArgumentNull(nameof(dataTable)); 83 } 84 if (string.IsNullOrEmpty(dataSetColumn)) 85 { 86 #if DEBUG 87 if (AdapterSwitches.DataSchema.TraceWarning) 88 { 89 Debug.WriteLine("explicit filtering of SourceColumn \"" + sourceColumn + "\""); 90 } 91 #endif 92 return null; 93 } 94 DataColumnCollection columns = dataTable.Columns; 95 Debug.Assert(null != columns, "GetDataColumnBySchemaAction: unexpected null DataColumnCollection"); 96 97 int index = columns.IndexOf(dataSetColumn); 98 if ((0 <= index) && (index < columns.Count)) 99 { 100 DataColumn dataColumn = columns[index]; 101 Debug.Assert(null != dataColumn, "GetDataColumnBySchemaAction: unexpected null dataColumn"); 102 103 if (!string.IsNullOrEmpty(dataColumn.Expression)) 104 { 105 #if DEBUG 106 if (AdapterSwitches.DataSchema.TraceError) 107 { 108 Debug.WriteLine("schema mismatch on DataColumn \"" + dataSetColumn + "\" which is a computed column"); 109 } 110 #endif 111 throw ADP.ColumnSchemaExpression(sourceColumn, dataSetColumn); 112 } 113 if ((null == dataType) || (dataType.IsArray == dataColumn.DataType.IsArray)) 114 { 115 #if DEBUG 116 if (AdapterSwitches.DataSchema.TraceInfo) 117 { 118 Debug.WriteLine("schema match on DataColumn \"" + dataSetColumn + "\""); 119 } 120 #endif 121 return dataColumn; 122 } 123 #if DEBUG 124 if (AdapterSwitches.DataSchema.TraceWarning) 125 { 126 Debug.WriteLine("schema mismatch on DataColumn \"" + dataSetColumn + "\" " + dataType.Name + " != " + dataColumn.DataType.Name); 127 } 128 #endif 129 throw ADP.ColumnSchemaMismatch(sourceColumn, dataType, dataColumn); 130 } 131 132 return CreateDataColumnBySchemaAction(sourceColumn, dataSetColumn, dataTable, dataType, schemaAction); 133 } 134 CreateDataColumnBySchemaAction(string sourceColumn, string dataSetColumn, DataTable dataTable, Type dataType, MissingSchemaAction schemaAction)135 internal static DataColumn CreateDataColumnBySchemaAction(string sourceColumn, string dataSetColumn, DataTable dataTable, Type dataType, MissingSchemaAction schemaAction) 136 { 137 Debug.Assert(dataTable != null, "Should not call with a null DataTable"); 138 if (string.IsNullOrEmpty(dataSetColumn)) 139 { 140 return null; 141 } 142 143 switch (schemaAction) 144 { 145 case MissingSchemaAction.Add: 146 case MissingSchemaAction.AddWithKey: 147 #if DEBUG 148 if (AdapterSwitches.DataSchema.TraceInfo) 149 { 150 Debug.WriteLine("schema add of DataColumn \"" + dataSetColumn + "\" <" + Convert.ToString(dataType, CultureInfo.InvariantCulture) + ">"); 151 } 152 #endif 153 return new DataColumn(dataSetColumn, dataType); 154 155 case MissingSchemaAction.Ignore: 156 #if DEBUG 157 if (AdapterSwitches.DataSchema.TraceWarning) 158 { 159 Debug.WriteLine("schema filter of DataColumn \"" + dataSetColumn + "\" <" + Convert.ToString(dataType, CultureInfo.InvariantCulture) + ">"); 160 } 161 #endif 162 return null; 163 164 case MissingSchemaAction.Error: 165 #if DEBUG 166 if (AdapterSwitches.DataSchema.TraceError) 167 { 168 Debug.WriteLine("schema error on DataColumn \"" + dataSetColumn + "\" <" + Convert.ToString(dataType, CultureInfo.InvariantCulture) + ">"); 169 } 170 #endif 171 throw ADP.ColumnSchemaMissing(dataSetColumn, dataTable.TableName, sourceColumn); 172 } 173 throw ADP.InvalidMissingSchemaAction(schemaAction); 174 } 175 ToString()176 public override string ToString() 177 { 178 return SourceColumn; 179 } 180 181 internal sealed class DataColumnMappingConverter : System.ComponentModel.ExpandableObjectConverter 182 { 183 // converter classes should have public ctor DataColumnMappingConverter()184 public DataColumnMappingConverter() 185 { 186 } 187 CanConvertTo(ITypeDescriptorContext context, Type destinationType)188 public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) 189 { 190 if (typeof(InstanceDescriptor) == destinationType) 191 { 192 return true; 193 } 194 return base.CanConvertTo(context, destinationType); 195 } 196 ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)197 public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) 198 { 199 if (null == destinationType) 200 { 201 throw ADP.ArgumentNull(nameof(destinationType)); 202 } 203 204 if ((typeof(InstanceDescriptor) == destinationType) && (value is DataColumnMapping)) 205 { 206 DataColumnMapping mapping = (DataColumnMapping)value; 207 208 object[] values = new object[] { mapping.SourceColumn, mapping.DataSetColumn }; 209 Type[] types = new Type[] { typeof(string), typeof(string) }; 210 211 ConstructorInfo ctor = typeof(DataColumnMapping).GetConstructor(types); 212 return new InstanceDescriptor(ctor, values); 213 } 214 return base.ConvertTo(context, culture, value, destinationType); 215 } 216 } 217 } 218 } 219