我有一个使用 MySQL 数据库的 C# .NET 3.5 项目。
我有一个对象Task
,我希望能够通过从一系列数据库表中提取它来创建它。
public class Task
{
public Task()
{
Values = new List<string>();
OtherValues = new List<string>();
Requirement = string.Empty;
Minimum = 1;
Children = new List<Foo>();
}
public IList<string> Values { get; set; }
public IList<string> OtherValues { get; set; }
public string Requirement { get; set; }
public int Minimum { get; set; }
public int Maximum { get; set; }
public IList<Foo> Children { get; set; }
}
我希望能够从 TaskList
中获取任务,它会在枚举器访问任务元素时懒惰地读取它们。
public class TaskList : IEnumerable<Task>
{
/* ... */
public IEnumerator<Task> GetEnumerator()
{
string query = @"SELECT my_task.*, `Order` FROM my_task ORDER BY `Order` DESC";
using (MySqlConnection connection = new MySqlConnection(connection_string_))
using (MySqlCommand command = connection.CreateCommand())
{
command.CommandText = query;
connection.Open();
using (MySqlDataReader reader = command.ExecuteReader())
{
yeild /* ??? */
}
}
}
}
这是怎么做到的?
最佳答案
您可以将其序列化为 XML 并将其存储为字符串。将以下函数添加到 Task
:
public XElement Serialize()
{
return new XElement("Task",
new XElement("Values",from val in Values select new XElement("Item",val)),
new XElement("OtherValues",from val in OtherValues select new XElement("Item",val)),
new XElement("Requirement",Requirement),
new XElement("Minimum",Minimum),
new XElement("Maximum",Maximum)
);
}
您需要将 using System.Linq;
和 using System.Xml.Linq;
放在 .cs 文件的顶部。
我没有写序列化 Children
的代码,因为我不知道数据类型 Foo
是什么样的,但你应该以类似的方式序列化它.完成后,您可以轻松地将 XML 写入数据库,然后将其读回(编写一个将 Xml 解析为 Task 对象的构造函数)
编辑(添加):
以下是接收 XML(或将字符串解析为 XML)的构造函数的示例:
public Task(string xmlSourceAsString):
this(XElement.Parse(xmlSourceAsString))
{
}
public Task(XElement xmlSource)
{
Values=(from itm in xmlSource.Element("Values").Elements("Item") select itm.Value).ToList();
OtherValues=(from itm in xmlSource.Element("OtherValues").Elements("Item") select itm.Value).ToList();
Requirement=xmlSource.Element("Requirement").Value;
Minimum=int.Parse(xmlSource.Element("Minimum").Value);
Maximum=int.Parse(xmlSource.Element("Maximum").Value);
}
编辑(解释):
您不能“按原样”将对象按原样存储在数据库中,因为它引用了其他对象。例如 - 列表 Values
与对象的其余部分不在内存中的同一位置,因为它是一个 ref 类型 - 它引用另一个对象,该对象位于内存中的不同位置.事实上,你的对象中唯一与主对象存储在同一位置的部分是 Minimum
和 Maximum
,它们是 ref 类型,所以如果你可以以某种方式按原样存储对象(可能是最懒惰的解决方案,如果可行的话),您将获得正确的最小值和最大值字段,但所有其他字段将指向存储任务对象时放置这些对象的内存地址,这现在很可能是无效指针(我说“最有可能”是因为它们也有可能(尽管很少见)指向合法对象,可能是同一类型的事件——但它们仍然不会有你的 数据。
如果您希望将对象及其所有数据存储在数据库中(或文件中。或通过网络传递给在另一台计算机上运行的进程),您必须 serialize它。就性能而言,最好的方法是将其序列化为二进制(C# 有一些工具,但它仍然比 XML 更复杂)。
Xml 还具有易于从大多数现代编程语言和数据库引擎读取的优势。 MySQL has some functions to read and write XML ,因此您可以更新数据库中的对象并从 MySQL 查询访问它的字段。
结论
您要求一个简单(惰性)、高效且与 sql 兼容(从 MySQL 查询访问对象字段)的解决方案。我说你只能有你的三个要求中的两个,但你可以选择哪两个:
如果您想要简单高效的东西,即使以失去兼容性为代价,请将您的对象序列化为二进制。的确,它不像 XML 那样简单,但是 .NET has some tools to help you with that .
如果您想要一些高效且兼容的东西,并且愿意为此做一些工作,您可以按照数据库的使用方式将您的对象放入 MySQL - 为引用对象的列表使用单独的表通过 OID 等。这需要一些工作,但是在您添加表并编写 MySQL 函数和处理所有内容的 C# 函数之后,您应该能够轻松地存储、检索和访问您的对象。
如果您想要一些简单且兼容的东西,并且您可以承受损失一些效率,请使用我的解决方案并将您的对象序列化为 XML。此是最懒惰的解决方案 - 除非有人知道可以自动序列化任何对象的库,否则 LINQ to XML 是最简单的方法,并且比任何其他解决方案需要的代码少得多。
关于c# - 从 MySQL 数据库中提取一个非平凡的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7679553/