使用 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");
我是 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");