重构C#代码,用于创建不使用中间字典的XML

时间:2014-01-29 11:15:33

标签: c# refactoring

如果有以下代码,通过SQL查询从表单中检索数据:

Id      subschemaName  locusName
MLST    MLST           LMO0558
MLST    MLST           LMO0563
MLVST   MLVST          LMO1305
MLVST   MLVST          LMO1089

我希望将其转换为XML:

<ResponseSubschemas>
    <organism>LMO</organism>
    <Subschemas>
        <Subschema>
            <id>MLST</id>
            <name>MLST</name>
            <loci>
                <locus>LMO0558</locus>
                <locus>LMO0563</locus>
            </loci>
        </Subschema>
        <Subschema>
            <id>MLVST</id>
            <name>MLVST</name>
            <loci>
                <locus>LMO1305</locus>
                <locus>LMO1089</locus>
            </loci>
        </Subschema>
    </Subschemas>
</ResponseSubschemas>

我是通过使用字典来实现的,但这是我第一次使用C#而且我确信必须有更高效的方法一次性完成这项工作?

string subschemaSQL =   "SELECT subschema.Id, subschema.name as subschemaName, locus.Name as locusName " + 
                        "FROM subschema " +
                        "LEFT JOIN subschemamembers ON subschemamembers.SubSchemaID = subschema.PrimKey " +
                        "LEFT JOIN locus ON subschemamembers.LocusID = locus.ID " +
                        "WHERE  subschema.OrganismID = ? " +
                        "ORDER BY subschema.Id, locusName";

XElement rootNode = new XElement("ResponseSubschemas", 
    new XElement("organism", organismID),
    new XElement("Subschemas"));
XElement subschemasNode = rootNode.Element("Subschemas");

DbDataReader subschemaReader = conn.Query(subschemaSQL, organismID);

Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>();
while (subschemaReader.Read())
{
    string subschemaDbID = (string)subschemaReader["Id"];
    XElement subschemaNode = new XElement("Subschema",
        new XElement("id", subschemaDbID),
        new XElement("name", subschemaReader["subschemaName"])
    );
    subschemasNode.Add(subschemaNode);
    string locusName = (string)subschemaReader["locusName"];
    if (dictionary.ContainsKey(subschemaDbID))
    {
        dictionary[subschemaDbID].Add(locusName);
    }
    else
    {
        dictionary.Add(subschemaDbID, new List<string> { locusName });
    }
}



IEnumerable<XElement> subschemaNodes = from element in
                                       subschemasNode.Elements("Subschema")
                                       select element;
foreach (XElement subschemaNode in subschemaNodes)
{
    string subschemaID = subschemaNode.Element("id").Value;
    XElement lociNode = new XElement("loci");
    foreach (string locusName in dictionary[subschemaID])
    {
        XElement locusNode = new XElement("locus", locusName);
        lociNode.Add(locusNode);
    }
    subschemaNode.Add(lociNode);

}

responseXml = rootNode.ToString();

1 个答案:

答案 0 :(得分:1)

这可能会稍微紧凑一些(尽管高层视角的内部执行与你所写的非常相似):

string subschemaSQL =   "SELECT subschema.Id, subschema.name as subschemaName, locus.Name as locusName " + 
                        "FROM subschema " +
                        "LEFT JOIN subschemamembers ON subschemamembers.SubSchemaID = subschema.PrimKey " +
                        "LEFT JOIN locus ON subschemamembers.LocusID = locus.ID " +
                        "WHERE  subschema.OrganismID = ? " +
                        "ORDER BY subschema.Id, locusName";

XElement rootNode = new XElement("ResponseSubschemas",
                                 new XElement("organism", organismID),
                                 new XElement("Subschemas"));
XElement subschemasNode = rootNode.Element("Subschemas");

//this should probably be used in a 'using' block,
//leaving your code intact for readability:
DbDataReader subschemaReader = conn.Query(subschemaSQL, organismID);

DataTable table = new DataTable();
table.Load(subschemaReader);

subSchemasNode.Add(
   table.Rows
        .Select(row => new {
                             Id = row["id"].ToString(),
                             SubschemaName = row["subschemaName"].ToString(),
                             LocusName = row["locusName"].ToString()
                           })
        .GroupBy(item => new { Id = item.Id, SubschemaName = item.SubschemaName)
        .Select(@group =>
                 new XElement("Subschema",
                              new XElement("id", @group.Key.Id),
                              new XElement("name", @group.Key.SubschemaName),
                              new XElement("loci", @group.Select(item => new XElement("locus", item.LocusName)).ToArray())))
        .ToArray());

基本上,您将所有数据加载到内存中DataTable,然后应用处理数据集的LINQ操作,避免显式创建字典。