Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将sql查询的结果映射到对象上?_C#_Sql - Fatal编程技术网

C# 如何将sql查询的结果映射到对象上?

C# 如何将sql查询的结果映射到对象上?,c#,sql,C#,Sql,目前,我正在使用类似以下内容: try { dr = SQL.Execute(sql); if(dr != null) { while(dr.Read()) { CustomObject c = new CustomObject(); c.Key = dr[0].ToString(); c.Value = dr[1].ToString(); c.Me

目前,我正在使用类似以下内容:

    try
    {
      dr = SQL.Execute(sql);

      if(dr != null) {
         while(dr.Read()) {
           CustomObject c = new CustomObject();
           c.Key = dr[0].ToString();
           c.Value = dr[1].ToString();
           c.Meta = dr[2].ToString();
           customerInfo.CustomerList.Add(c);
         }
      }
      else
      {
          customerInfo.ErrorDetails="No records found";
      } 
    private IEnumerable<dynamic> ReaderToAnonymmous(SqlCommand comm) {
        using (var reader = comm.ExecuteReader()) {
            var schemaTable = reader.GetSchemaTable();

            List<string> colnames = new List<string>();
            foreach (DataRow row in schemaTable.Rows) {
                colnames.Add(row["ColumnName"].ToString());
            }

            while (reader.Read()) {
                var data = new ExpandoObject() as IDictionary<string, Object>;
                foreach (string colname in colnames) {
                    var val = reader[colname];
                    data.Add(colname, Convert.IsDBNull(val) ? null : val);
                }

                yield return (ExpandoObject)data;
            }
        }
    }
        using (var connection = new SqlConnection(ConnectionString))
        {
            connection.Open();
            IList<CustomObject> result = connection.Query<CustomObject>(sql, commandType: CommandType.Text).ToList();
        }
有没有办法直接进行映射(假设列名与字段名匹配),而不是手动进行分配


然而,有一个要求是,我希望通过当前使用sql查询的方法来实现这一点,而不是使用纯粹基于LINQ的方法。首先,SQL查询足够大,涉及复杂的连接,并且已经过全面测试,所以我现在不想引入更多的bug。有什么建议吗?

一个简单的解决方案是为您的
CustomObject
创建一个构造函数,它接受
DataRow
(来自示例,因此如果它是另一个类,请更正我)

在您的新构造函数中,按照您在自己的示例中所做的做

public CustomObject(DataRow row)
{
    Key = row[0].ToString();
    // And so on...
}
另一种方法是引入泛型,并在SQL类中创建一个新函数

示例(代码取自):

//此函数应驻留在SQL类中。
公共IEnumerable可执行对象(字符串sql)
{
列表项=新列表();
var data=ExecuteDataTable(sql);//您可能需要为sql类构建一个ExecuteDataTable。
foreach(data.Rows中的变量行)
{
T item=(T)Activator.CreateInstance(typeof(T),row);
项目。添加(项目);
}
退货项目;
}
用法示例:

public IEnumerable<CustomObject> GetCustomObjects()
{
    return SQL.ExecuteObject<CustomObject>("SELECT * FROM CustomObject");
}
public IEnumerable GetCustomObjects()
{
返回SQL.ExecuteObject(“从CustomObject中选择*);
}

我已经在LinqPad中测试了这段代码,它应该可以工作。

您可以通过为您的需求创建一个通用方法来实现。还可以将新方法作为数据表的扩展

    public static List<T> ToList<T>(this DataTable table) where T : class, new()
{
    try
    {
        List<T> list = new List<T>();

        foreach (var row in table.AsEnumerable())
        {
            T obj = new T();

            foreach (var prop in obj.GetType().GetProperties())
            {
                try
                {
                    PropertyInfo propertyInfo = obj.GetType().GetProperty(prop.Name);
                    propertyInfo.SetValue(obj, Convert.ChangeType(row[prop.Name], propertyInfo.PropertyType), null);
                }
                catch
                {
                    continue;
                }
            }

            list.Add(obj);
        }

        return list;
    }
    catch
    {
        return null;
    }
}
公共静态列表ToList(此数据表),其中T:class,new()
{
尝试
{
列表=新列表();
foreach(表中的var行。AsEnumerable())
{
T obj=新的T();
foreach(obj.GetType().GetProperties()中的var prop)
{
尝试
{
PropertyInfo PropertyInfo=obj.GetType().GetProperty(prop.Name);
propertyInfo.SetValue(obj,Convert.ChangeType(行[prop.Name],propertyInfo.PropertyType),null);
}
抓住
{
继续;
}
}
列表。添加(obj);
}
退货清单;
}
抓住
{
返回null;
}
}
}

用法:

    DataTable dtCustomer = GetCustomers();
    List<CustomObject> CustomObjectList = dtCustomer.ToList<CustomObject>();
DataTable dtCustomer=GetCustomers();
List CustomObjectList=dtCustomer.ToList();

您应该研究MicroORMs。与提供必须使用的SDL的常规ORM不同,MicroORM允许您使用自己的SQL查询,并且只提供从SQL结果集到C#对象以及从C#对象到SQL参数的映射


我最喜欢的是,它还提供了一个查询生成器,它使用您自己的SQL,但对参数号进行了一些整洁的操作。

以下函数接受一个SQL字符串和一个对象,它要求对象在select语句中的每一列都有一个属性。必须实例化该对象

public object SqlToSingleObject(string sSql, object o)
{
    MySql.Data.MySqlClient.MySqlDataReader oRead;
    using (ConnectionHelper oDb = new ConnectionHelper())
    {
        oRead = oDb.Execute(sSql);
        if (oRead.Read())
        {
            for (int i = 0; i < oRead.FieldCount; i++)
            {
                System.Reflection.PropertyInfo propertyInfo = o.GetType().GetProperty(oRead.GetName(i));
                propertyInfo.SetValue(o, Convert.ChangeType(oRead[i], propertyInfo.PropertyType), null);
            }

            return o;
        }
        else
        {
            return null;
        }
    }
}
public对象SqlToSingleObject(字符串sSql,对象o)
{
MySql.Data.MySqlClient.MySqlDataReader或ead;
使用(ConnectionHelper oDb=new ConnectionHelper())
{
oRead=oDb.Execute(sSql);
if(oRead.Read())
{
对于(int i=0;i
假设:如果您只需要用于序列化或简单即席输出的对象

您可以像这样使用
ExpandoObject
SqlDataReader.GetSchemaTable()

    try
    {
      dr = SQL.Execute(sql);

      if(dr != null) {
         while(dr.Read()) {
           CustomObject c = new CustomObject();
           c.Key = dr[0].ToString();
           c.Value = dr[1].ToString();
           c.Meta = dr[2].ToString();
           customerInfo.CustomerList.Add(c);
         }
      }
      else
      {
          customerInfo.ErrorDetails="No records found";
      } 
    private IEnumerable<dynamic> ReaderToAnonymmous(SqlCommand comm) {
        using (var reader = comm.ExecuteReader()) {
            var schemaTable = reader.GetSchemaTable();

            List<string> colnames = new List<string>();
            foreach (DataRow row in schemaTable.Rows) {
                colnames.Add(row["ColumnName"].ToString());
            }

            while (reader.Read()) {
                var data = new ExpandoObject() as IDictionary<string, Object>;
                foreach (string colname in colnames) {
                    var val = reader[colname];
                    data.Add(colname, Convert.IsDBNull(val) ? null : val);
                }

                yield return (ExpandoObject)data;
            }
        }
    }
        using (var connection = new SqlConnection(ConnectionString))
        {
            connection.Open();
            IList<CustomObject> result = connection.Query<CustomObject>(sql, commandType: CommandType.Text).ToList();
        }
private IEnumerable readerToAnonymous(SqlCommand comm){
使用(var reader=comm.ExecuteReader()){
var schemaTable=reader.GetSchemaTable();
List colnames=新列表();
foreach(schemaTable.Rows中的DataRow行){
添加(行[“ColumnName”].ToString());
}
while(reader.Read()){
var data=新的ExpandooObject()作为IDictionary;
foreach(colnames中的字符串colname){
var val=读取器[colname];
data.Add(colname,Convert.IsDBNull(val)?null:val);
}
收益率返回(ExpandoObject)数据;
}
}
}

尽管发布了更快的解决方案(我发布了这篇文章,作为临时SQL/Reader结果/输出的替代惰性方法)

在搜索此答案时,我发现您可以使用Dapper library:

您可以使用以下内容:

    try
    {
      dr = SQL.Execute(sql);

      if(dr != null) {
         while(dr.Read()) {
           CustomObject c = new CustomObject();
           c.Key = dr[0].ToString();
           c.Value = dr[1].ToString();
           c.Meta = dr[2].ToString();
           customerInfo.CustomerList.Add(c);
         }
      }
      else
      {
          customerInfo.ErrorDetails="No records found";
      } 
    private IEnumerable<dynamic> ReaderToAnonymmous(SqlCommand comm) {
        using (var reader = comm.ExecuteReader()) {
            var schemaTable = reader.GetSchemaTable();

            List<string> colnames = new List<string>();
            foreach (DataRow row in schemaTable.Rows) {
                colnames.Add(row["ColumnName"].ToString());
            }

            while (reader.Read()) {
                var data = new ExpandoObject() as IDictionary<string, Object>;
                foreach (string colname in colnames) {
                    var val = reader[colname];
                    data.Add(colname, Convert.IsDBNull(val) ? null : val);
                }

                yield return (ExpandoObject)data;
            }
        }
    }
        using (var connection = new SqlConnection(ConnectionString))
        {
            connection.Open();
            IList<CustomObject> result = connection.Query<CustomObject>(sql, commandType: CommandType.Text).ToList();
        }
使用(var连接=新的SqlConnection(ConnectionString))
{
connection.Open();
IList result=connection.Query(sql,commandType:commandType.Text).ToList();
}
的答案很好,但是,如果列名与属性名不完全匹配,则它不起作用

因此,首先您需要创建一个自定义属性。然后使用您试图反序列化的类中的属性,最后,您希望反序列化DataTable

自定义属性 我们创建一个自定义属性,该属性将应用于类内部的属性。我们创建的类具有属性
Name
,稍后我们将使用该属性从数据表中获取正确的列

[AttributeUsage(AttributeTargets.Property, Inherited = false)]
public class MySqlColName : Attribute
{
    private string _name = "";
    public string Name { get => _name; set => _name = value; }

    public MySqlColName(string name)
    {
        _name = name;
    }
}
类进行反序列化 接下来,在我们要填充的类中,我们将使用我们刚才使用的属性
[MySqlColName]
声明将链接到类中属性的列名