[C#] Mutual conversion between entity class and DataTable, entity reflection dynamic traversal column

In actual projects, mutual conversion between data is often used, and serialization and deserialization are common scenarios. Here we only briefly talk about the conversion between entity classes and DataTables, which can be used in different business scenarios.

Table of Contents

  • 1. DataTable to Model
  • 2. Model to DataTable
  • 3. The concept of reflection
    • 3.1, Type type
    • 3.2, Assembly assembly
    • 3.3, MemberInfo member information
    • 3.4, PropertyInfo attribute information
  • 4. Frequently asked questions

1. DataTable to Model

To convert C# DataTable to Model entity class, you can use reflection to get DataTable columns and values, and assign values by instantiating Model class.

1) Convert DataTable to Model class

  • sample code
using System;
using System.Collections.Generic;
using System.Data;
using System. Reflection;

public static class DataTableExtensions
{<!-- -->
    public static List<T> ToList<T>(this DataTable dataTable) where T : class, new()
    {<!-- -->
        List<T> list = new List<T>();

        foreach (DataRow row in dataTable.Rows)
        {<!-- -->
            T obj = new T();

            foreach (DataColumn col in dataTable.Columns)
            {<!-- -->
                PropertyInfo property = typeof(T).GetProperty(col.ColumnName);
                if (property != null & amp; & amp; row[col] != DBNull. Value)
                {<!-- -->
                    property. SetValue(obj, row[col]);
                }
            }

            list.Add(obj);
        }

        return list;
    }
}

2) Convert DataTable to the specified Model entity class

public class Person
{<!-- -->
    public int Id {<!-- --> get; set; }
    public string Name {<!-- --> get; set; }
    public int Age {<!-- --> get; set; }
}

DataTable dataTable = new DataTable();
dataTable.Columns.Add("Id", typeof(int));
dataTable.Columns.Add("Name", typeof(string));
dataTable.Columns.Add("Age", typeof(int));

dataTable.Rows.Add(1, "John", 25);
dataTable.Rows.Add(2, "Jane", 30);
dataTable.Rows.Add(3, "Mike", 40);

List<Person> persons = dataTable. ToList<Person>();
  • running result

The above code will create a List of Person entity classes containing DataTable data. The data of each column will be assigned to the corresponding property of Person.
Note that the Person class in the above example is just an example, you can create a custom entity class according to your own needs, and match attributes according to the column names and types of the DataTable. In addition, you need to ensure that the corresponding attribute exists, and the value type of the column is compatible with the attribute type.

2. Model to DataTable

To convert a C# entity to a DataTable through reflection, you can use the classes in the System.Reflection namespace to access the properties and values of the entity and add them to the DataTable.
1) Use reflection to convert entities to DataTable

using System;
using System.Data;
using System. Reflection;

public static class EntityExtensions
{<!-- -->
    public static DataTable ToDataTable<T>(this T[] entities)
    {<!-- -->
        DataTable dataTable = new DataTable(typeof(T).Name);

        PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

        foreach (PropertyInfo propInfo in properties)
        {<!-- -->
            dataTable.Columns.Add(propInfo.Name, propInfo.PropertyType);
        }

        foreach (T entity in entities)
        {<!-- -->
            object[] values = new object[properties. Length];
            for (int i = 0; i < properties. Length; i ++ )
            {<!-- -->
                values[i] = properties[i]. GetValue(entity);
            }

            dataTable.Rows.Add(values);
        }

        return dataTable;
    }
}

2) Convert any entity array to DataTable

public class Person
{<!-- -->
    public int Id {<!-- --> get; set; }
    public string Name {<!-- --> get; set; }
    public int Age {<!-- --> get; set; }
}

Person[] persons = new Person[]
{<!-- -->
    new Person {<!-- --> Id = 1, Name = "John", Age = 25 },
    new Person {<!-- --> Id = 2, Name = "Jane", Age = 30 },
    new Person {<!-- --> Id = 3, Name = "Mike", Age = 40 }
};

DataTable dataTable = persons. ToDataTable();
  • running result

The above code will create a DataTable containing the data of the Person entity array. Each attribute will be a column of this DataTable, and each entity instance will form a row of the DataTable.
Please note that the entity class Person in the above example is just an example, you can create a custom entity class according to your own needs, and use the corresponding attributes and types.

3. Reflection concept

Reflection in C# refers to the ability to obtain, inspect, and manipulate assemblies, types, members (such as fields, properties, methods, etc.) at runtime. Reflection provides a set of classes and methods that can dynamically obtain assembly and type information at runtime and use this information to create objects, call methods, access properties, and more.

Here are some key concepts and uses:

3.1, Type

The Type type is at the heart of reflection and represents types loaded at runtime. The Type type provides methods and properties for obtaining type information, such as name, base class, implemented interfaces, properties, methods, fields, and so on. With the Type type, you can dynamically obtain and manipulate type information.

3.2, Assembly

The Assembly type represents an assembly, which is a logical unit that contains executable files, dynamically linked libraries, or containers for code. Through reflection, you can load and inspect assembly information, including types, members, attributes, and more. You can use Assembly types to load assemblies, get types in assemblies, create objects, and more.

3.3, MemberInfo member information

The MemberInfo type represents members of a type, such as fields, properties, methods, events, and so on. It provides methods to obtain information such as the member’s name, type, and access modifiers.

3.4, PropertyInfo attribute information

The PropertyInfo type represents properties of a type, and it provides methods and properties for getting and setting property values.

With reflection, you can implement many dynamic and flexible functions, such as:

  • Dynamically create objects and call methods: dynamically create objects based on type information at runtime, and call object methods.
  • Dynamically access and modify attribute values: Obtain object attribute information at runtime and dynamically modify attribute values.
  • Get and inspect type information: Get type information at runtime, such as name, base class, implemented interfaces, members, etc.
  • Load and use external assemblies: Dynamically load and use external assemblies to access and manipulate types and members within them at runtime.
  • Write generic code: Use reflection to write generic, flexible code that adapts to different types and members.

It should be noted that reflection will bring performance loss to a certain extent, because it needs to obtain and check type information at runtime. Therefore, when using reflection, you need to weigh the relationship between performance and flexibility, and pay attention to avoid unnecessary reflection operations.

4. FAQ

1) When an entity class has a member defined as a nullable type, if it is not processed, an error will be reported


2) In DataSet, it is indeed not supported to directly use the System.Nullable<> type.

If you want to use nullable types in DataTable columns, you can use the System.Object type and set it to DBNull.Value when needed to represent null values.

DataTable dataTable = new DataTable();

// add a nullable integer column
DataColumn nullableIntColumn = new DataColumn("NullableInt", typeof(object));
dataTable.Columns.Add(nullableIntColumn);

// add a nullable string column
DataColumn nullableStringColumn = new DataColumn("NullableString", typeof(object));
dataTable.Columns.Add(nullableStringColumn);

In the above code, we created a DataTable object dataTable and added two columns: NullableInt and NullableString.

To define a column as a nullable type, we use typeof(object) to define the type of the column, which allows arbitrary objects, and can be set to DBNull.Value to represent null values when needed.

3) Store a nullable value in a column of the DataTable, for example:

DataRow row = dataTable. NewRow();
row["NullableInt"] = DBNull.Value; // The nullable integer is empty, represented by DBNull.Value
row["NullableString"] = DBNull.Value; // The nullable string is empty, represented by DBNull.Value
dataTable.Rows.Add(row);

In this way, you can handle nullable types in DataTable columns and use DBNull.Value to represent null values. Please note that when reading and processing data, you need to check whether the value of a column is DBNull.Value to determine whether it is null