简体   繁体   English

如何从数据库动态设置值

[英]How can I dynamically set values from the database

My search queries will always return one row and put it into a datatable. 我的搜索查询将始终返回一行并将其放入数据表中。

Is there a way that I can check if the column name and the property name matches, then set the value? 有没有一种方法可以检查列名和属性名是否匹配,然后设置值?

For example: 例如:

    SELECT * FROM mytable WHERE ID = 10;

Query returns column names: "ID, ScriptName, Type, Flags, VerifiedBuild" and their values. 查询返回列名:“ID,了ScriptName,类型,旗,VerifiedBuild”和他们的价值观。

Then run a foreach statement checking if the column name and property name match and set the property values below. 然后运行一条foreach语句,检查列名和属性名是否匹配,并在下面设置属性值。

    public int ID { get; set; }
    public int ScriptName { get; set; }
    public int Type { get; set; }
    public int Flags { get; set; }
    public int VerifiedBuild { get; set; }

You can do it very easly using EntityLite , at its core, EntityLite can materialize entities from data readers. 您可以非常轻松地使用EntityLite做到这一点,EntityLite可以从数据读取器中实现实体。 This funtionallity is publically exposed. 这种功能是公开的。

Imagine you have a method like the following; 假设您有如下方法:

public IDataReader GetDataReaderFromQuery()
{
    //TODO: implement this method
    throw new NotImplementedException();
}

And one POCO entity: 还有一个POCO实体:

public class MyEntity 
{
    // properties go here
}

you can use FisrtOrDefault, ToEnumberable and ToList extension methods on the datareader to get POCO entities: 您可以在数据读取器上使用FisrtOrDefault,ToEnumberable和ToList扩展方法来获取POCO实体:

using inercya.EntityLite;
using inercya.EntityLite.Extensions;

//......

MyEntity SomeMethod()
{
    using (reader = GetDataReaderFromQuery())
    {

         return reader.FirstOrDefault<MyEntity>();
    }
}

EntityLite will build a method at runtime using DynamicMethod that materializes an entity of that type from that specific datareader. EntityLite将在运行时使用DynamicMethod构建一个方法,该方法从该特定的数据读取器中实现该类型的实体。 The method is cached, so if you need to materialize more entities of that type from datareaders with the same schema, the method is reused. 该方法已缓存,因此,如果您需要从具有相同架构的数据读取器中实现更多该类型的实体,则可以重用该方法。 It is almost as fast as de best handwritten code. 它几乎和最好的手写代码一样快。

With the help of FastDynamic (a tiny library that helps you to efficiently create objects and to access properties of compile-time-unkonwn types), you could write the following data reader extension methods: 借助FastDynamic (一个可帮助您有效创建对象并访问编译时未知类型的属性的微型库),您可以编写以下数据读取器扩展方法:

using FastDynamic;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Sample
{
    public static class DataReaderExtensions
    {
        private static void SetPropertiesFromDataReader(IDataReader reader, object entity)
        {
            if (reader == null || entity == null) throw new ArgumentNullException();
            Type entityType = entity.GetType();
            var setters = entityType.GetSetters();
            for (int fieldIndex = 0; fieldIndex < reader.FieldCount; fieldIndex++)
            {
                var fieldName = reader.GetName(fieldIndex);
                Setter setter = null;
                if (!string.IsNullOrEmpty(fieldName) && setters.TryGetValue(fieldName, out setter))
                {
                    if (!reader.IsDBNull(fieldIndex))
                    {
                        setter(entity, reader.GetValue(i));
                    }
                }
            }
        }

        public static IEnumerable<T> ToEnumberable<T>(this IDataReader reader) where T:class, new()
        {
            Type entityType = typeof(T);
            Func<object> activator = entityType.GetActivator();
            while (reader.Read())
            {
                var entity = activator();
                SetPropertiesFromDataReader(reader, entity);
                yield return (T)entity;
            }
        }

        public T FirstOrDefault<T>(this IDataReader reader) where T : class, new()
        {
            return reader.ToEnumberable<T>().FirstOrDefault();
        }

        public List<T> ToList<T>(this IDataReader reader) where T : class, new()
        {
            return reader.ToEnumberable<T>().ToList();
        }

    }
}

Yes. 是。 You need to use reflection. 您需要使用反射。 By using reflection you can get parameter names in an array and you can compare names in a for loop. 通过使用反射,您可以获得数组中的参数名称,并且可以在for循环中比较名称。

ParameterInfo 参数信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM