[SQL] 형식화 된 목록에서 IDataReader에 가져 오기
SQL형식화 된 목록에서 IDataReader에 가져 오기
나는 백만 요소 목록
다음과 같이 저는 현재 SqlBulkCopy의를 사용하고 있습니다 :
private string FastInsertCollection(string tableName, DataTable tableData)
{
string sqlConn = ConfigurationManager.ConnectionStrings[SubSonicConfig.DefaultDataProvider.ConnectionStringName].ConnectionString;
using (SqlBulkCopy s = new SqlBulkCopy(sqlConn, SqlBulkCopyOptions.TableLock))
{
s.DestinationTableName = tableName;
s.BatchSize = 5000;
s.WriteToServer(tableData);
s.BulkCopyTimeout = SprocTimeout;
s.Close();
}
return sqlConn;
}
나는 내 컬렉션에서 DataTable을 구축 음속의 MyObjectCollection.ToDataTable ()를 사용합니다. 그러나,이 메모리에서 개체를 복제하고 비효율적이다. 나는 메모리 내 컬렉션을 중복되지 않도록 대신 DataTable을의 IDataReader에를 사용하는 SqlBulkCopy.WriteToServer 방법을 사용하고 싶습니다.
내 목록에서 IDataReader에를 얻을 수있는 가장 쉬운 방법은 무엇입니까? 나는 사용자 정의 데이터 판독기를 구현할 수있는 가정 (여기에 같은 http://blogs.microsoft.co.il/blogs/aviwortzel/archive/2008/05/06/implementing-sqlbulkcopy-in-linq-to-sql.aspx) 그러나 나는 일반적인 코드의 무리를 작성하지 않고 할 수있는 간단한 일이 있어야합니다.
편집하다: 하나 쉽게 개체의 컬렉션에서 IDataReader에를 생성 할 수 표시되지 않습니다. 내가 프레임 워크에 내장 된 뭔가를 기대했다하더라도 현재의 대답을 수락.
해결법
-
==============================
1.이 게시물에 코드에서 최신 버전을 가져옵니다
이 게시물에 코드에서 최신 버전을 가져옵니다
일반 시력 코드 이탈처럼 아무것도 : 여기에 꽤 완벽하게 구현되지 않습니다. 당신은 IList를 IEnumerable, IEnumerable을 (에고 된 IQueryable)에 비해 IDataReader에 인스턴스를 할 수 있습니다. 이 독자의 제네릭 형식 매개 변수를 노출 할 강력한 이유가 없다 그것을 생략하여, 나는 IEnumerable을 < 'A> (익명 형식)을 허용 할 수 있습니다. 테스트를 참조하십시오.
소스, 적은 xmldocs는 몇 테스트를 여기에 포함시킬 짧은 충분하다. xmldocs와 소스의 휴식 및 테스트 Salient.Data에서 여기에있다.
using System; using System.Linq; using NUnit.Framework; namespace Salient.Data.Tests { [TestFixture] public class EnumerableDataReaderEFFixture { [Test] public void TestEnumerableDataReaderWithIQueryableOfAnonymousType() { var ctx = new NorthwindEntities(); var q = ctx.Orders.Where(o => o.Customers.CustomerID == "VINET").Select( o => new { o.OrderID, o.OrderDate, o.Customers.CustomerID, Total = o.Order_Details.Sum( od => od.Quantity*((float) od.UnitPrice - ((float) od.UnitPrice*od.Discount))) }); var r = new EnumerableDataReader(q); while (r.Read()) { var values = new object[4]; r.GetValues(values); Console.WriteLine("{0} {1} {2} {3}", values); } } } }
using System; using System.Collections; using System.Collections.Generic; using System.Data; using NUnit.Framework; namespace Salient.Data.Tests { public class DataObj { public string Name { get; set; } public int Age { get; set; } } [TestFixture] public class EnumerableDataReaderFixture { private static IEnumerable<DataObj> DataSource { get { return new List<DataObj> { new DataObj {Name = "1", Age = 16}, new DataObj {Name = "2", Age = 26}, new DataObj {Name = "3", Age = 36}, new DataObj {Name = "4", Age = 46} }; } } [Test] public void TestIEnumerableCtor() { var r = new EnumerableDataReader(DataSource, typeof(DataObj)); while (r.Read()) { var values = new object[2]; int count = r.GetValues(values); Assert.AreEqual(2, count); values = new object[1]; count = r.GetValues(values); Assert.AreEqual(1, count); values = new object[3]; count = r.GetValues(values); Assert.AreEqual(2, count); Assert.IsInstanceOf(typeof(string), r.GetValue(0)); Assert.IsInstanceOf(typeof(int), r.GetValue(1)); Console.WriteLine("Name: {0}, Age: {1}", r.GetValue(0), r.GetValue(1)); } } [Test] public void TestIEnumerableOfAnonymousType() { // create generic list Func<Type, IList> toGenericList = type => (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(new[] { type })); // create generic list of anonymous type IList listOfAnonymousType = toGenericList(new { Name = "1", Age = 16 }.GetType()); listOfAnonymousType.Add(new { Name = "1", Age = 16 }); listOfAnonymousType.Add(new { Name = "2", Age = 26 }); listOfAnonymousType.Add(new { Name = "3", Age = 36 }); listOfAnonymousType.Add(new { Name = "4", Age = 46 }); var r = new EnumerableDataReader(listOfAnonymousType); while (r.Read()) { var values = new object[2]; int count = r.GetValues(values); Assert.AreEqual(2, count); values = new object[1]; count = r.GetValues(values); Assert.AreEqual(1, count); values = new object[3]; count = r.GetValues(values); Assert.AreEqual(2, count); Assert.IsInstanceOf(typeof(string), r.GetValue(0)); Assert.IsInstanceOf(typeof(int), r.GetValue(1)); Console.WriteLine("Name: {0}, Age: {1}", r.GetValue(0), r.GetValue(1)); } } [Test] public void TestIEnumerableOfTCtor() { var r = new EnumerableDataReader(DataSource); while (r.Read()) { var values = new object[2]; int count = r.GetValues(values); Assert.AreEqual(2, count); values = new object[1]; count = r.GetValues(values); Assert.AreEqual(1, count); values = new object[3]; count = r.GetValues(values); Assert.AreEqual(2, count); Assert.IsInstanceOf(typeof(string), r.GetValue(0)); Assert.IsInstanceOf(typeof(int), r.GetValue(1)); Console.WriteLine("Name: {0}, Age: {1}", r.GetValue(0), r.GetValue(1)); } } // remaining tests omitted for brevity } }
/*! * Project: Salient.Data * File : EnumerableDataReader.cs * http://spikes.codeplex.com * * Copyright 2010, Sky Sanders * Dual licensed under the MIT or GPL Version 2 licenses. * See LICENSE.TXT * Date: Sat Mar 28 2010 */ using System; using System.Collections; using System.Collections.Generic; namespace Salient.Data { /// <summary> /// Creates an IDataReader over an instance of IEnumerable<> or IEnumerable. /// Anonymous type arguments are acceptable. /// </summary> public class EnumerableDataReader : ObjectDataReader { private readonly IEnumerator _enumerator; private readonly Type _type; private object _current; /// <summary> /// Create an IDataReader over an instance of IEnumerable<>. /// /// Note: anonymous type arguments are acceptable. /// /// Use other constructor for IEnumerable. /// </summary> /// <param name="collection">IEnumerable<>. For IEnumerable use other constructor and specify type.</param> public EnumerableDataReader(IEnumerable collection) { // THANKS DANIEL! foreach (Type intface in collection.GetType().GetInterfaces()) { if (intface.IsGenericType && intface.GetGenericTypeDefinition() == typeof (IEnumerable<>)) { _type = intface.GetGenericArguments()[0]; } } if (_type ==null && collection.GetType().IsGenericType) { _type = collection.GetType().GetGenericArguments()[0]; } if (_type == null ) { throw new ArgumentException( "collection must be IEnumerable<>. Use other constructor for IEnumerable and specify type"); } SetFields(_type); _enumerator = collection.GetEnumerator(); } /// <summary> /// Create an IDataReader over an instance of IEnumerable. /// Use other constructor for IEnumerable<> /// </summary> /// <param name="collection"></param> /// <param name="elementType"></param> public EnumerableDataReader(IEnumerable collection, Type elementType) : base(elementType) { _type = elementType; _enumerator = collection.GetEnumerator(); } /// <summary> /// Helper method to create generic lists from anonymous type /// </summary> /// <param name="type"></param> /// <returns></returns> public static IList ToGenericList(Type type) { return (IList) Activator.CreateInstance(typeof (List<>).MakeGenericType(new[] {type})); } /// <summary> /// Return the value of the specified field. /// </summary> /// <returns> /// The <see cref="T:System.Object"/> which will contain the field value upon return. /// </returns> /// <param name="i">The index of the field to find. /// </param><exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"/>. /// </exception><filterpriority>2</filterpriority> public override object GetValue(int i) { if (i < 0 || i >= Fields.Count) { throw new IndexOutOfRangeException(); } return Fields[i].Getter(_current); } /// <summary> /// Advances the <see cref="T:System.Data.IDataReader"/> to the next record. /// </summary> /// <returns> /// true if there are more rows; otherwise, false. /// </returns> /// <filterpriority>2</filterpriority> public override bool Read() { bool returnValue = _enumerator.MoveNext(); _current = returnValue ? _enumerator.Current : _type.IsValueType ? Activator.CreateInstance(_type) : null; return returnValue; } } }
// <copyright project="Salient.Data" file="ObjectDataReader.cs" company="Sky Sanders"> // This source is a Public Domain Dedication. // Please see http://spikes.codeplex.com/ for details. // Attribution is appreciated // </copyright> // <version>1.0</version> using System; using System.Collections.Generic; using System.Data; using Salient.Reflection; namespace Salient.Data { public abstract class ObjectDataReader : IDataReader { protected bool Closed; protected IList<DynamicProperties.Property> Fields; protected ObjectDataReader() { } protected ObjectDataReader(Type elementType) { SetFields(elementType); Closed = false; } #region IDataReader Members public abstract object GetValue(int i); public abstract bool Read(); #endregion #region Implementation of IDataRecord public int FieldCount { get { return Fields.Count; } } public virtual int GetOrdinal(string name) { for (int i = 0; i < Fields.Count; i++) { if (Fields[i].Info.Name == name) { return i; } } throw new IndexOutOfRangeException("name"); } object IDataRecord.this[int i] { get { return GetValue(i); } } public virtual bool GetBoolean(int i) { return (Boolean) GetValue(i); } public virtual byte GetByte(int i) { return (Byte) GetValue(i); } public virtual char GetChar(int i) { return (Char) GetValue(i); } public virtual DateTime GetDateTime(int i) { return (DateTime) GetValue(i); } public virtual decimal GetDecimal(int i) { return (Decimal) GetValue(i); } public virtual double GetDouble(int i) { return (Double) GetValue(i); } public virtual Type GetFieldType(int i) { return Fields[i].Info.PropertyType; } public virtual float GetFloat(int i) { return (float) GetValue(i); } public virtual Guid GetGuid(int i) { return (Guid) GetValue(i); } public virtual short GetInt16(int i) { return (Int16) GetValue(i); } public virtual int GetInt32(int i) { return (Int32) GetValue(i); } public virtual long GetInt64(int i) { return (Int64) GetValue(i); } public virtual string GetString(int i) { return (string) GetValue(i); } public virtual bool IsDBNull(int i) { return GetValue(i) == null; } object IDataRecord.this[string name] { get { return GetValue(GetOrdinal(name)); } } public virtual string GetDataTypeName(int i) { return GetFieldType(i).Name; } public virtual string GetName(int i) { if (i < 0 || i >= Fields.Count) { throw new IndexOutOfRangeException("name"); } return Fields[i].Info.Name; } public virtual int GetValues(object[] values) { int i = 0; for (; i < Fields.Count; i++) { if (values.Length <= i) { return i; } values[i] = GetValue(i); } return i; } public virtual IDataReader GetData(int i) { // need to think about this one throw new NotImplementedException(); } public virtual long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length) { // need to keep track of the bytes got for each record - more work than i want to do right now // http://msdn.microsoft.com/en-us/library/system.data.idatarecord.getbytes.aspx throw new NotImplementedException(); } public virtual long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length) { // need to keep track of the bytes got for each record - more work than i want to do right now // http://msdn.microsoft.com/en-us/library/system.data.idatarecord.getchars.aspx throw new NotImplementedException(); } #endregion #region Implementation of IDataReader public virtual void Close() { Closed = true; } public virtual DataTable GetSchemaTable() { var dt = new DataTable(); foreach (DynamicProperties.Property field in Fields) { dt.Columns.Add(new DataColumn(field.Info.Name, field.Info.PropertyType)); } return dt; } public virtual bool NextResult() { throw new NotImplementedException(); } public virtual int Depth { get { throw new NotImplementedException(); } } public virtual bool IsClosed { get { return Closed; } } public virtual int RecordsAffected { get { // assuming select only? return -1; } } #endregion #region Implementation of IDisposable public virtual void Dispose() { Fields = null; } #endregion protected void SetFields(Type elementType) { Fields = DynamicProperties.CreatePropertyMethods(elementType); } } }
// <copyright project="Salient.Reflection" file="DynamicProperties.cs" company="Sky Sanders"> // This source is a Public Domain Dedication. // Please see http://spikes.codeplex.com/ for details. // Attribution is appreciated // </copyright> // <version>1.0</version> using System; using System.Collections.Generic; using System.Reflection; using System.Reflection.Emit; namespace Salient.Reflection { /// <summary> /// Gets IL setters and getters for a property. /// /// started with http://jachman.wordpress.com/2006/08/22/2000-faster-using-dynamic-method-calls/ /// </summary> public static class DynamicProperties { #region Delegates public delegate object GenericGetter(object target); public delegate void GenericSetter(object target, object value); #endregion public static IList<Property> CreatePropertyMethods(Type T) { var returnValue = new List<Property>(); foreach (PropertyInfo prop in T.GetProperties()) { returnValue.Add(new Property(prop)); } return returnValue; } public static IList<Property> CreatePropertyMethods<T>() { var returnValue = new List<Property>(); foreach (PropertyInfo prop in typeof (T).GetProperties()) { returnValue.Add(new Property(prop)); } return returnValue; } /// <summary> /// Creates a dynamic setter for the property /// </summary> /// <param name="propertyInfo"></param> /// <returns></returns> public static GenericSetter CreateSetMethod(PropertyInfo propertyInfo) { /* * If there's no setter return null */ MethodInfo setMethod = propertyInfo.GetSetMethod(); if (setMethod == null) return null; /* * Create the dynamic method */ var arguments = new Type[2]; arguments[0] = arguments[1] = typeof (object); var setter = new DynamicMethod( String.Concat("_Set", propertyInfo.Name, "_"), typeof (void), arguments, propertyInfo.DeclaringType); ILGenerator generator = setter.GetILGenerator(); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Castclass, propertyInfo.DeclaringType); generator.Emit(OpCodes.Ldarg_1); if (propertyInfo.PropertyType.IsClass) generator.Emit(OpCodes.Castclass, propertyInfo.PropertyType); else generator.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType); generator.EmitCall(OpCodes.Callvirt, setMethod, null); generator.Emit(OpCodes.Ret); /* * Create the delegate and return it */ return (GenericSetter) setter.CreateDelegate(typeof (GenericSetter)); } /// <summary> /// Creates a dynamic getter for the property /// </summary> /// <param name="propertyInfo"></param> /// <returns></returns> public static GenericGetter CreateGetMethod(PropertyInfo propertyInfo) { /* * If there's no getter return null */ MethodInfo getMethod = propertyInfo.GetGetMethod(); if (getMethod == null) return null; /* * Create the dynamic method */ var arguments = new Type[1]; arguments[0] = typeof (object); var getter = new DynamicMethod( String.Concat("_Get", propertyInfo.Name, "_"), typeof (object), arguments, propertyInfo.DeclaringType); ILGenerator generator = getter.GetILGenerator(); generator.DeclareLocal(typeof (object)); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Castclass, propertyInfo.DeclaringType); generator.EmitCall(OpCodes.Callvirt, getMethod, null); if (!propertyInfo.PropertyType.IsClass) generator.Emit(OpCodes.Box, propertyInfo.PropertyType); generator.Emit(OpCodes.Ret); /* * Create the delegate and return it */ return (GenericGetter) getter.CreateDelegate(typeof (GenericGetter)); } #region Nested type: Property public class Property { public GenericGetter Getter; public PropertyInfo Info; public GenericSetter Setter; public Property(PropertyInfo info) { Info = info; Setter = CreateSetMethod(info); Getter = CreateGetMethod(info); } } #endregion ///// <summary> ///// An expression based Getter getter found in comments. untested. ///// Q: i don't see a reciprocal setter expression? ///// </summary> ///// <typeparam name="T"></typeparam> ///// <param name="propName"></param> ///// <returns></returns> //public static Func<T> CreateGetPropValue<T>(string propName) //{ // var param = Expression.Parameter(typeof(object), "container"); // var func = Expression.Lambda( // Expression.Convert(Expression.PropertyOrField(Expression.Convert(param, typeof(T)), propName), typeof(object)), param); // return (Func<T>)func.Compile(); //} } }
-
==============================
2.당신은 마크 Gravell의 FastMember을 사용할 수 있습니다 :
당신은 마크 Gravell의 FastMember을 사용할 수 있습니다 :
IDataReader reader = ObjectReader.Create(myEnumerable); //all columns IDataReader reader = ObjectReader.Create(myEnumerable, "Id", "Name", "Description");
생성 로직을 얻어 추출 할뿐 아니라 더 빨리 반사보다 속성 / 필드 값을 얻을 IL을 사용한다.
-
==============================
3.그의 초기 답변 스카이 샌더스 덕분에, 그것은 큰 도움이되었다.
그의 초기 답변 스카이 샌더스 덕분에, 그것은 큰 도움이되었다.
나는 스카이 샌더스 'EnumerableDataReader의 일반 버전을 썼다 그러나 나는 다음과 같이 변경했다 :
난이 도움이되기를 바랍니다 당신이 어떤 발언, 수정 또는 개선이있는 경우, 그렇게 말하십시오 :
/// <summary> /// IDataReader that can be used for "reading" an IEnumerable<T> collection /// </summary> public class EnumerableDataReader<T> : IDataReader { /// <summary> /// Constructor /// </summary> /// <param name="collection">The collection to be read</param> /// <param name="fields">The list of public field/properties to read from each T (in order), OR if no fields are given only one field will be available: T itself</param> public EnumerableDataReader(IEnumerable<T> collection, params string[] fields) { if (collection == null) throw new ArgumentNullException("collection"); m_Enumerator = collection.GetEnumerator(); if (m_Enumerator == null) throw new NullReferenceException("collection does not implement GetEnumerator"); SetFields(fields); } private IEnumerator<T> m_Enumerator; private T m_Current = default(T); private bool m_EnumeratorState = false; private void SetFields(ICollection<string> fields) { if (fields.Count > 0) { Type type = typeof(T); foreach (string field in fields) { PropertyInfo pInfo = type.GetProperty(field); if (pInfo != null) m_Fields.Add(new Property(pInfo)); else { FieldInfo fInfo = type.GetField(field); if (fInfo != null) m_Fields.Add(new Field(fInfo)); else throw new NullReferenceException(string.Format("EnumerableDataReader<T>: Missing property or field '{0}' in Type '{1}'.", field, type.Name)); } } } else m_Fields.Add(new Self()); } private List<BaseField> m_Fields = new List<BaseField>(); #region IDisposable Members public void Dispose() { if (m_Enumerator != null) { m_Enumerator.Dispose(); m_Enumerator = null; m_Current = default(T); m_EnumeratorState = false; } m_Closed = true; } #endregion #region IDataReader Members public void Close() { m_Closed = true; } private bool m_Closed = false; public int Depth { get { return 0; } } public DataTable GetSchemaTable() { var dt = new DataTable(); foreach (BaseField field in m_Fields) { dt.Columns.Add(new DataColumn(field.Name, field.Type)); } return dt; } public bool IsClosed { get { return m_Closed; } } public bool NextResult() { return false; } public bool Read() { if (IsClosed) throw new InvalidOperationException("DataReader is closed"); m_EnumeratorState = m_Enumerator.MoveNext(); m_Current = m_EnumeratorState ? m_Enumerator.Current : default(T); return m_EnumeratorState; } public int RecordsAffected { get { return -1; } } #endregion #region IDataRecord Members public int FieldCount { get { return m_Fields.Count; } } public Type GetFieldType(int i) { if (i < 0 || i >= m_Fields.Count) throw new IndexOutOfRangeException(); return m_Fields[i].Type; } public string GetDataTypeName(int i) { return GetFieldType(i).Name; } public string GetName(int i) { if (i < 0 || i >= m_Fields.Count) throw new IndexOutOfRangeException(); return m_Fields[i].Name; } public int GetOrdinal(string name) { for (int i = 0; i < m_Fields.Count; i++) if (m_Fields[i].Name == name) return i; throw new IndexOutOfRangeException("name"); } public bool IsDBNull(int i) { return GetValue(i) == null; } public object this[string name] { get { return GetValue(GetOrdinal(name)); } } public object this[int i] { get { return GetValue(i); } } public object GetValue(int i) { if (IsClosed || !m_EnumeratorState) throw new InvalidOperationException("DataReader is closed or has reached the end of the enumerator"); if (i < 0 || i >= m_Fields.Count) throw new IndexOutOfRangeException(); return m_Fields[i].GetValue(m_Current); } public int GetValues(object[] values) { int length = Math.Min(m_Fields.Count, values.Length); for (int i = 0; i < length; i++) values[i] = GetValue(i); return length; } public bool GetBoolean(int i) { return (bool)GetValue(i); } public byte GetByte(int i) { return (byte)GetValue(i); } public char GetChar(int i) { return (char)GetValue(i); } 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 float GetFloat(int i) { return (float)GetValue(i); } public Guid GetGuid(int i) {return (Guid)GetValue(i); } public short GetInt16(int i) { return (short)GetValue(i); } public int GetInt32(int i) { return (int)GetValue(i); } public long GetInt64(int i) { return (long)GetValue(i); } public string GetString(int i) { return (string)GetValue(i); } public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length) { throw new NotSupportedException(); } public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length) { throw new NotSupportedException(); } public IDataReader GetData(int i) { throw new NotSupportedException(); } #endregion #region Helper Classes private abstract class BaseField { public abstract Type Type { get; } public abstract string Name { get; } public abstract object GetValue(T instance); protected static void AddGetter(Type classType, string fieldName, Func<T, object> getter) { m_GetterDictionary.Add(string.Concat(classType.FullName, fieldName), getter); } protected static Func<T, object> GetGetter(Type classType, string fieldName) { Func<T, object> getter = null; if (m_GetterDictionary.TryGetValue(string.Concat(classType.FullName, fieldName), out getter)) return getter; return null; } private static Dictionary<string, Func<T, object>> m_GetterDictionary = new Dictionary<string, Func<T, object>>(); } private class Property : BaseField { public Property(PropertyInfo info) { m_Info = info; m_DynamicGetter = CreateGetMethod(info); } private PropertyInfo m_Info; private Func<T, object> m_DynamicGetter; public override Type Type { get { return m_Info.PropertyType; } } public override string Name { get { return m_Info.Name; } } public override object GetValue(T instance) { //return m_Info.GetValue(instance, null); // Reflection is slow return m_DynamicGetter(instance); } // Create dynamic method for faster access instead via reflection private Func<T, object> CreateGetMethod(PropertyInfo propertyInfo) { Type classType = typeof(T); Func<T, object> dynamicGetter = GetGetter(classType, propertyInfo.Name); if (dynamicGetter == null) { ParameterExpression instance = Expression.Parameter(classType); MemberExpression property = Expression.Property(instance, propertyInfo); UnaryExpression convert = Expression.Convert(property, typeof(object)); dynamicGetter = (Func<T, object>)Expression.Lambda(convert, instance).Compile(); AddGetter(classType, propertyInfo.Name, dynamicGetter); } return dynamicGetter; } } private class Field : BaseField { public Field(FieldInfo info) { m_Info = info; m_DynamicGetter = CreateGetMethod(info); } private FieldInfo m_Info; private Func<T, object> m_DynamicGetter; public override Type Type { get { return m_Info.FieldType; } } public override string Name { get { return m_Info.Name; } } public override object GetValue(T instance) { //return m_Info.GetValue(instance); // Reflection is slow return m_DynamicGetter(instance); } // Create dynamic method for faster access instead via reflection private Func<T, object> CreateGetMethod(FieldInfo fieldInfo) { Type classType = typeof(T); Func<T, object> dynamicGetter = GetGetter(classType, fieldInfo.Name); if (dynamicGetter == null) { ParameterExpression instance = Expression.Parameter(classType); MemberExpression property = Expression.Field(instance, fieldInfo); UnaryExpression convert = Expression.Convert(property, typeof(object)); dynamicGetter = (Func<T, object>)Expression.Lambda(convert, instance).Compile(); AddGetter(classType, fieldInfo.Name, dynamicGetter); } return dynamicGetter; } } private class Self : BaseField { public Self() { m_Type = typeof(T); } private Type m_Type; public override Type Type { get { return m_Type; } } public override string Name { get { return string.Empty; } } public override object GetValue(T instance) { return instance; } } #endregion }
from https://stackoverflow.com/questions/2258310/get-an-idatareader-from-a-typed-list by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] SQL Server 2005의 시간 차이를 찾기 위해 두 날짜를 비교하는 방법, 날짜 조작 (0) | 2020.04.19 |
---|---|
[SQL] 2008 SQL에 외래 키 관계에서 삭제 정책을 생성? (0) | 2020.04.19 |
[SQL] SQL Server에서 "SET ANSI_NULLS ON"은 무엇을 의미합니까? (0) | 2020.04.19 |
[SQL] 나는 VARCHAR 또는 INT의 기본 키가있는 테이블을 설계해야 하는가? (0) | 2020.04.19 |
[SQL] 중복을 무시하고, 다른 한 테이블에서 행을 복사 (0) | 2020.04.18 |