使用 C# 查询 MySQL

Querying MySQL with C#

我是 C# 的新手,正在尝试了解如何使用 C# 查询我的数据库,同时还能将查询结果保存到列表中。我以为我已经对事物进行了半排序,但我收到无法从字符串转换为 class?

的错误

我无法找到模拟我在这里尝试做的事情的东西(使用 class 变量),否则我认为其他一些示例使用的似乎是 C# 的标准泛型对于列表可能会起作用。我更习惯于使用 Python,因此找不到我习惯于在特定主题上找到的文档级别。任何帮助表示赞赏。谢谢!

using System.Collections.Generic;
namespace FilmData
{
    public class Director
    {
        public Director()
        {
            Films = new List<Film>();
        }
        
        public int DirectorID { get; set; }
        public string DirectorName { get; set;}

        public List<Film> Films { get; set; }
    }

    public class Film
    {   
        public int FilmID { get; set; }
        public string FilmName { get; set;}
        public int FilmReleaseYear { get; set; }
        public float FilmAvgRating { get; set;}
    }

    public static void Main ()
    {
        try
        {
            using (MySqlConnection conn = new MySqlConnection("server=localhost;user=user123;database=myFilms;port=port;password=somePW"))
            Console.WriteLine("Connecting to MySQL...");
                    conn.Open();

                    List<Director> director = new List<Director>();   // <-- trying to create list item

                    string sql = "SELECT * FROM Director";
                    using (MySqlCommand cmd = new MySqlCommand(sql, conn))
                    {
                        MySqlDataReader rdr = cmd.ExecuteReader();
                        while (rdr.Read())
                        {
                            var AddToList = rdr[0] + ",   " + rdr[1];
                            director.Add(AddToList);  // <-- error here
                            
                            /* want to be able to write DB values to list
                            / utilizing the structure of DB class, but
                            / do not know the correct formatting to use
                            / List<Director> DirectorList = new Director();
                            / does not allow for me to use .Add() with
                            / string
                           */
                        }
                        
                    }
                    conn.Close();
                    Console.WriteLine("Done.");
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }
}

您必须从 datareader 映射到您的 .net 对象。

while (rdr.Read())
 {
   Director director = new Director();
   director.DirectorID = (int)reader["DirectorId"]; <-- check here what is exact column name 
   director.DirectorName = reader["DirectorName"].ToString(),

   // fill other poperties ..
 }

或者你可以更优雅地使用反射来做这个转换。为每一行提供注释以显示每一行在做什么。

public List<T> PopulateList(SqlDataReader reader)
{
        var results = new List<T>(); // create generic list T will be incoming type
        var properties = typeof(T).GetProperties(); // get all poperties defined in your object
    
        while (reader.Read())
        {
            var item = Activator.CreateInstance<T>(); // create instance of object
            foreach (var property in typeof(T).GetProperties()) // loop through each properties in your object
            {
                if (!reader.IsDBNull(reader.GetOrdinal(property.Name)))
                {  // if that exists in the datareader
                    Type convertTo = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType;
                    property.SetValue(item, Convert.ChangeType(reader[property.Name], convertTo), null); // set the property from reader
                }
            }
            results.Add(item); // add to result list
        }
        return results;
}

然后调用它

YourClass<Director> obj = new YourClass<Director>();
var directorList = obj.PopulateList(reader);

您在另一条评论中询问您的要求是否不寻常/是否有其他方式

您的需求很普遍; “select 来自数据库的行 table 并将它们转换为 C# 对象”是使用数据库的常见要求。在过去,我们是按照您的方式做的:编写查询、添加参数、执行它、从 reader 中提取数据、从列表中提取对象,重复直到处理完行,return 列表。这是令人难以置信的乏味、无聊、盲目的编码,这让任何有创造力的开发人员都希望他们在做一些真正有趣的事情(这就是为什么它会被归为初级开发人员,可怜的傻瓜)

当开发人员面临重复、无聊的任务时,他们会找到一种方法将其交给计算机。 Navoneel 在这里做到了;他们没有按 属性 逐列复制 属性,而是开发了一种技术来查看 属性 名称、列名称,并将它们分配在一起,以便可以在循环中完成- 这是一个巧妙的技巧。

随着时间的推移,其他开发人员也开发了其他类似的想法,将其发展成为规范完善且功能齐全的库,可以完成所有这些以及更多工作,然后他们免费提供这些库。快速浏览一下:

小巧玲珑

运行Whosebug 的技术。它是数据库连接的一组扩展,将 运行 您提供的查询并将其转换为对象、对象列表、相关对象集等

你看起来像这样:

//we make a connection
using var c = new MySqlConnection("...conn str");

//then call the Query method that installing Dapper added onto the connection
List<Director> dirs = c.Query<Director>("SELECT * FROM director");

这会获取所有董事,并且如果列的名称与 c# 属性 相匹配,就可以简单地计算出来

如果列名与 props 不匹配,重命名列:

//c# props are called FirstName, LastName, db are Name, Surname
var dirs = c.Query<Director>("SELECT Name as FirstName, Surname as LastName FROM director");

您可以在查询中使用参数:

var dirs = c.Query<Director>("SELECT * FROM director WHERE surname like @ln", new { on = "Smith%");

你只能得到一个:

var dir = c.QueryFirst<Director>("SELECT * FROM director WHERE surname like @ln LIMIT 1", new { on = "Smith%");

它支持 first、single、async、执行更新、将数组自动扩展到 IN 列表...这么多东西需要整个网站(例如 www.dapper-tutorial.com 才能完成)。看看...

Entity Framework

也许是 Dapper 的下一步;一个设备,您只需指向您的数据库并说“对此进行逆向工程”,它就会扫描数据库并将每个 table 和关系转换为一组 c# 对象,其中的列转到属性,对象全部 link 对彼此。然后,您只需将数据库视为这些相关对象的大图来查询数据库——您不必自己编写 sql。

示例:

//all directors
context.Directors.ToList();

//directors names starting smith
context.Directors.Where(d => d.LastName.StartsWith("Smith"));

//directors directing more than 3 companies
context.Directors.Where(d => d.Companies.Count() > 3);

//Microsoft, including all director details 
context.Comapnies.Include(c => c.Directors).First(c => c.Name == "Microsoft");