从MySQL数据库中提取一个非平凡的对象

时间:2011-10-06 19:37:28

标签: c# mysql

我有一个使用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 /* ??? */
            }
        }
    }
}

这是怎么做到的?

1 个答案:

答案 0 :(得分:1)

您可以将其序列化为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类型 - 它指的是位于内存中不同位置的另一个对象。事实上,对象中与主对象存储在同一位置的唯一部分是MinimumMaximum,它们是ref类型,所以如果你能以某种方式将对象存储为是(最懒的解决方案,如果它工作),你会得到你的最小和最大字段,但所有其他字段将指向存储Task对象时放置的那些对象的内存地址,这些对象现在很可能是无效指针(我说“最有可能”,因为它们也可能(尽管很少见)它们会指向合法的对象,也许是相同类型的事件 - 但它们仍然没有你的数据。 / p>

如果您希望对象的所有数据存储在数据库中(或在文件中。或传递给通过网络在另一台计算机上运行的进程),则必须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是最简单的方法,并且需要的代码比任何其他解决方案少得多。