Skip to content

Instantly share code, notes, and snippets.

@isurusndr
Last active October 18, 2016 04:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save isurusndr/450cfd0b2b19cd92ca322685d648877d to your computer and use it in GitHub Desktop.
Save isurusndr/450cfd0b2b19cd92ca322685d648877d to your computer and use it in GitHub Desktop.
Custom implementation of IDataReader class. It can be used as an input data reader to feed data from an IEnumerable source to SqlBulkCopy.WriteToServer method. This implementation can be used with Entity Framework.
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Linq.Mapping;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MySpace
{
public class EnumerableDataReader<TEntity> : IDataReader
{
protected bool _Closed;
private readonly IEnumerator<TEntity> _Enumerator;
private readonly IList<ColumnMapping> _ColumnMappingList;
private readonly string _TableName;
public string TableName
{
get { return _TableName; }
}
public IDictionary<string, int> ColumnMappingList
{
get
{
return _ColumnMappingList.Select(column =>
new { column.ColumnName, column.ColumnIndex })
.ToDictionary(x => x.ColumnName, y => y.ColumnIndex);
}
}
private class ColumnMapping
{
public int ColumnIndex { get; set; }
public string ColumnName { get; set; }
public Type ColumnType { get; set; }
public Func<object, object> ColumnGetter { get; set; }
}
public EnumerableDataReader(IEnumerable<TEntity> entities)
{
_Enumerator = entities.GetEnumerator();
_ColumnMappingList = new List<ColumnMapping>();
var entityType = entities.GetType()
.GetInterface("IEnumerable`1")
.GetGenericArguments()[0];
_TableName = (entityType.GetCustomAttributes(
typeof(TableAttribute), false) as TableAttribute[])[0].Name;
var properties = entityType.GetProperties();
for (int index = 0; index < properties.Length; index++)
{
var property = properties[index];
var columns = property.GetCustomAttributes(typeof(ColumnAttribute), false)
as ColumnAttribute[];
foreach (var column in columns)
{
//Check if this property repserent a updatable column
if ((!column.DbType.Contains("IDENTITY")) &&
(!column.IsDbGenerated) &&
(!column.IsVersion))
{
_ColumnMappingList.Add(new ColumnMapping()
{
ColumnIndex = index,
ColumnName = column.Name ?? property.Name,
ColumnType = property.GetType(),
ColumnGetter = row => property.GetValue(row, null)
});
}
}
}
_Closed = false;
}
public void Close()
{
_Closed = true;
}
public int Depth
{
get { throw new NotImplementedException(); }
}
public DataTable GetSchemaTable()
{
var dt = new DataTable();
foreach (ColumnMapping mapping in _ColumnMappingList)
{
dt.Columns.Add(new DataColumn(mapping.ColumnName, mapping.ColumnType));
}
return dt;
}
public bool IsClosed
{
get { return _Closed; }
}
public bool NextResult()
{
return false;
}
public bool Read()
{
return _Enumerator.MoveNext();
}
public int RecordsAffected
{
get { return -1; }
}
public void Dispose()
{
if (_Enumerator != null)
{
_Enumerator.Dispose();
}
_Closed = true;
}
public int FieldCount
{
get
{
return _ColumnMappingList.Count;
}
}
public bool GetBoolean(int i)
{
return (Boolean) GetValue(i);
}
public byte GetByte(int i)
{
return (Byte) GetValue(i);
}
public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
{
throw new NotImplementedException();
}
public char GetChar(int i)
{
return (Char) GetValue(i);
}
public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
{
throw new NotImplementedException();
}
public IDataReader GetData(int i)
{
return (i == 0) ? this : null;
}
public string GetDataTypeName(int i)
{
return GetFieldType(i).Name;
}
public DateTime GetDateTime(int i)
{
return (DateTime) GetValue(i);
}
public decimal GetDecimal(int i)
{
return (Decimal) GetValue(i);
}
public double GetDouble(int i)
{
return (Double) GetValue(i);
}
public Type GetFieldType(int i)
{
return _ColumnMappingList
.Where(column => column.ColumnIndex == i)
.Single()
.ColumnType;
}
public float GetFloat(int i)
{
return (float) GetValue(i);
}
public Guid GetGuid(int i)
{
return (Guid) GetValue(i);
}
public short GetInt16(int i)
{
return (Int16) GetValue(i);
}
public int GetInt32(int i)
{
return (Int32) GetValue(i);
}
public long GetInt64(int i)
{
return (Int64) GetValue(i);
}
public string GetName(int i)
{
return _ColumnMappingList
.Where(column => column.ColumnIndex == i)
.Single()
.ColumnName;
}
public int GetOrdinal(string name)
{
return _ColumnMappingList
.Where(column => column.ColumnName == name)
.Single()
.ColumnIndex;
}
public string GetString(int i)
{
return (string) GetValue(i);
}
public object GetValue(int i)
{
return _ColumnMappingList.Where(column => column.ColumnIndex == i)
.Single()
.ColumnGetter(_Enumerator.Current);
}
public int GetValues(object[] values)
{
int i = 0;
for (; i < _ColumnMappingList.Count; i++)
{
if (values.Length <= i)
{
return i;
}
values[i] = GetValue(i);
}
return i;
}
public bool IsDBNull(int i)
{
return GetValue(i) == null;
}
public object this[string name]
{
get { return this[GetOrdinal(name)]; }
}
public object this[int i]
{
get { return GetValue(i); }
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment