Convert DataTable to IEnumerable

前端 未结 8 1579
梦毁少年i
梦毁少年i 2020-11-29 22:50

I am trying to convert a DataTable to an IEnumerable. Where T is a custom type I created. I know I can do it by creating a List but I was thinking if t

相关标签:
8条回答
  • 2020-11-29 23:22

    Simple method using System.Data.DataSetExtensions:

    table.AsEnumerable().Select(row => new TankReading{
            TankReadingsID = Convert.ToInt32(row["TRReadingsID"]),
            TankID = Convert.ToInt32(row["TankID"]),
            ReadingDateTime = Convert.ToDateTime(row["ReadingDateTime"]),
            ReadingFeet = Convert.ToInt32(row["ReadingFeet"]),
            ReadingInches = Convert.ToInt32(row["ReadingInches"]),
            MaterialNumber = row["MaterialNumber"].ToString(),
            EnteredBy = row["EnteredBy"].ToString(),
            ReadingPounds = Convert.ToDecimal(row["ReadingPounds"]),
            MaterialID = Convert.ToInt32(row["MaterialID"]),
            Submitted = Convert.ToBoolean(row["Submitted"]),
        });
    

    Or:

    TankReading TankReadingFromDataRow(DataRow row){
        return new TankReading{
            TankReadingsID = Convert.ToInt32(row["TRReadingsID"]),
            TankID = Convert.ToInt32(row["TankID"]),
            ReadingDateTime = Convert.ToDateTime(row["ReadingDateTime"]),
            ReadingFeet = Convert.ToInt32(row["ReadingFeet"]),
            ReadingInches = Convert.ToInt32(row["ReadingInches"]),
            MaterialNumber = row["MaterialNumber"].ToString(),
            EnteredBy = row["EnteredBy"].ToString(),
            ReadingPounds = Convert.ToDecimal(row["ReadingPounds"]),
            MaterialID = Convert.ToInt32(row["MaterialID"]),
            Submitted = Convert.ToBoolean(row["Submitted"]),
        };
    }
    
    // Now you can do this
    table.AsEnumerable().Select(row => return TankReadingFromDataRow(row));
    

    Or, better yet, create a TankReading(DataRow r) constructor, then this becomes:

        table.AsEnumerable().Select(row => return new TankReading(row));
    
    0 讨论(0)
  • 2020-11-29 23:26

    I wrote an article on this subject over here. I think it could help you.

    Typically it's doing something like that:

    static void Main(string[] args)
    {
        // Convert from a DataTable source to an IEnumerable.
        var usersSourceDataTable = CreateMockUserDataTable();
        var usersConvertedList = usersSourceDataTable.ToEnumerable<User>();
    
        // Convert from an IEnumerable source to a DataTable.
        var usersSourceList = CreateMockUserList();
        var usersConvertedDataTable = usersSourceList.ToDataTable<User>();
    }
    
    0 讨论(0)
  • 2020-11-29 23:29

    Nothing wrong with that implementation. You might give the yield keyword a shot, see how you like it:

    private IEnumerable<TankReading> ConvertToTankReadings(DataTable dataTable)
        {
            foreach (DataRow row in dataTable.Rows)
            {
                yield return new TankReading
                                      {
                                          TankReadingsID = Convert.ToInt32(row["TRReadingsID"]),
                                          TankID = Convert.ToInt32(row["TankID"]),
                                          ReadingDateTime = Convert.ToDateTime(row["ReadingDateTime"]),
                                          ReadingFeet = Convert.ToInt32(row["ReadingFeet"]),
                                          ReadingInches = Convert.ToInt32(row["ReadingInches"]),
                                          MaterialNumber = row["MaterialNumber"].ToString(),
                                          EnteredBy = row["EnteredBy"].ToString(),
                                          ReadingPounds = Convert.ToDecimal(row["ReadingPounds"]),
                                          MaterialID = Convert.ToInt32(row["MaterialID"]),
                                          Submitted = Convert.ToBoolean(row["Submitted"]),
                                      };
            }
    
        }
    

    Also the AsEnumerable isn't necessary, as List<T> is already an IEnumerable<T>

    0 讨论(0)
  • 2020-11-29 23:33

    Universal extension method for DataTable. May be somebody be interesting. Idea creating dynamic properties I take from another post: https://stackoverflow.com/a/15819760/8105226

        public static IEnumerable<dynamic> AsEnumerable(this DataTable dt)
        {
            List<dynamic> result = new List<dynamic>();
            Dictionary<string, object> d;
            foreach (DataRow dr in dt.Rows)
            {
                d = new Dictionary<string, object>();
    
                foreach (DataColumn dc in dt.Columns)
                    d.Add(dc.ColumnName, dr[dc]);
    
                result.Add(GetDynamicObject(d));
            }
            return result.AsEnumerable<dynamic>();
        }
    
        public static dynamic GetDynamicObject(Dictionary<string, object> properties)
        {
            return new MyDynObject(properties);
        }
    
        public sealed class MyDynObject : DynamicObject
        {
            private readonly Dictionary<string, object> _properties;
    
            public MyDynObject(Dictionary<string, object> properties)
            {
                _properties = properties;
            }
    
            public override IEnumerable<string> GetDynamicMemberNames()
            {
                return _properties.Keys;
            }
    
            public override bool TryGetMember(GetMemberBinder binder, out object result)
            {
                if (_properties.ContainsKey(binder.Name))
                {
                    result = _properties[binder.Name];
                    return true;
                }
                else
                {
                    result = null;
                    return false;
                }
            }
    
            public override bool TrySetMember(SetMemberBinder binder, object value)
            {
                if (_properties.ContainsKey(binder.Name))
                {
                    _properties[binder.Name] = value;
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
    
    0 讨论(0)
  • 2020-11-29 23:39

    There's also a DataSetExtension method called "AsEnumerable()" (in System.Data) that takes a DataTable and returns an Enumerable. See the MSDN doc for more details, but it's basically as easy as:

    dataTable.AsEnumerable()
    

    The downside is that it's enumerating DataRow, not your custom class. A "Select()" LINQ call could convert the row data, however:

    private IEnumerable<TankReading> ConvertToTankReadings(DataTable dataTable)
    {
        return dataTable.AsEnumerable().Select(row => new TankReading      
                {      
                    TankReadingsID = Convert.ToInt32(row["TRReadingsID"]),      
                    TankID = Convert.ToInt32(row["TankID"]),      
                    ReadingDateTime = Convert.ToDateTime(row["ReadingDateTime"]),      
                    ReadingFeet = Convert.ToInt32(row["ReadingFeet"]),      
                    ReadingInches = Convert.ToInt32(row["ReadingInches"]),      
                    MaterialNumber = row["MaterialNumber"].ToString(),      
                    EnteredBy = row["EnteredBy"].ToString(),      
                    ReadingPounds = Convert.ToDecimal(row["ReadingPounds"]),      
                    MaterialID = Convert.ToInt32(row["MaterialID"]),      
                    Submitted = Convert.ToBoolean(row["Submitted"]),      
                });
    }
    
    0 讨论(0)
  • 2020-11-29 23:40

    If you want to convert any DataTable to a equivalent IEnumerable vector function.

    Please take a look at the following generic function, this may help your needs (you may need to include write cases for different datatypes based on your needs).

    /// <summary>
        /// Get entities from DataTable
        /// </summary>
        /// <typeparam name="T">Type of entity</typeparam>
        /// <param name="dt">DataTable</param>
        /// <returns></returns>
        public IEnumerable<T> GetEntities<T>(DataTable dt)
        {
            if (dt == null)
            {
                return null;
            }
    
            List<T> returnValue = new List<T>();
            List<string> typeProperties = new List<string>();
    
            T typeInstance = Activator.CreateInstance<T>();
    
            foreach (DataColumn column in dt.Columns)
            {
                var prop = typeInstance.GetType().GetProperty(column.ColumnName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
                if (prop != null)
                {
                    typeProperties.Add(column.ColumnName);
                }
            }
    
            foreach (DataRow row in dt.Rows)
            {
                T entity = Activator.CreateInstance<T>();
    
                foreach (var propertyName in typeProperties)
                {
    
                    if (row[propertyName] != DBNull.Value)
                    {
                        string str = row[propertyName].GetType().FullName;
    
                        if (entity.GetType().GetProperty(propertyName).PropertyType == typeof(System.String))
                        {
                            object Val = row[propertyName].ToString();
                            entity.GetType().GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public).SetValue(entity, Val, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, null, null);
                        }
                        else if (entity.GetType().GetProperty(propertyName).PropertyType == typeof(System.Guid)) 
                        {
                            object Val = Guid.Parse(row[propertyName].ToString());
                            entity.GetType().GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public).SetValue(entity, Val, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, null, null);
                        }
                        else
                        {
                            entity.GetType().GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public).SetValue(entity, row[propertyName], BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, null, null);
                        }
                    }
                    else
                    {
                        entity.GetType().GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public).SetValue(entity, null, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, null, null);
                    }
                }
    
                returnValue.Add(entity);
            }
    
            return returnValue.AsEnumerable();
        }
    
    0 讨论(0)
提交回复
热议问题