繁体   English   中英

如何通过Linq-to-XML使用数据更新现有实体?

[英]How do I update an existing entity with data via Linq-to-XML?

我正在使用Linq-to-Xml读取XML并更新现有的数据结构。 现在,我有以下代码可以做到这一点:

        // Load all the test plan details
        var details = doc.Descendants()
                         .Select(x => new
                         {
                             Name = x.Attribute("name").ToStringValue(),
                             DbName = x.Attribute(DATABASE_ATTR).ToStringValue(),
                             Login = x.Attribute(USERNAME_ATTR).ToStringValue(),
                             Password = x.Attribute(PASSWORD_ATTR).ToStringValue(),
                             AppSource = x.Attribute(APPSOURCE_ATTR).ToStringValue()
                         })
                         .First();


        testPlan.Name = details.Name;
        testPlan.DatabaseName = details.DbName;
        testPlan.LoginUsername = details.Login;
        testPlan.LoginPassword = details.Password;
        testPlan.ApplicationSource = details.AppSource;
    }

这让我有点烦,因为我必须创建一个临时变量并执行数据传输。 我有什么方法可以直接从Linq语句中更新testPlan变量,这可以减少一步? 我无法通过将更新代码添加到.Select()语句中来使其工作。

以下应该工作:

doc.Descendants().First()
   .Select(x => 
           {
               testPlan.Name= x.Attribute("name").ToStringValue();
               testPlan.DatabaseName = x.Attribute(DATABASE_ATTR)
                                        .ToStringValue();
               testPlan.LoginUsername = x.Attribute(USERNAME_ATTR)
                                         .ToStringValue();
               testPlan.LoginPassword = x.Attribute(PASSWORD_ATTR)
                                         .ToStringValue();
               testPlan.ApplicationSource = x.Attribute(APPSOURCE_ATTR)
                                             .ToStringValue();
               return testPlan;
           })
    .ToList();

在中间对First的调用是为了确保仅将第一个后代的属性分配给testPlan的属性。 最后的ToList用于真正执行Select的代码。

尽管此方法有效,但我不建议您使用它,因为它以一种并非为之创建的方式使用LINQ。 此外,很容易将其创建为错误:

  • 如果忘记了First ,则testPlan将包含XML中最后一个元素的属性值,因为将对每个元素执行选择代码并覆盖这些属性。
  • 如果忘记了对ToList的调用或强制执行的类似方法,则Select内的代码将永远不会执行。

因此,基本上,问题是,您创造了很多引入错误的可能性。

我将通过以下方式实现这种方式:

var x = doc.Descendants.First();
testPlan.Name= x.Attribute("name").ToStringValue();
testPlan.DatabaseName = x.Attribute(DATABASE_ATTR).ToStringValue();
testPlan.LoginUsername = x.Attribute(USERNAME_ATTR).ToStringValue();
testPlan.LoginPassword = x.Attribute(PASSWORD_ATTR).ToStringValue();
testPlan.ApplicationSource = x.Attribute(APPSOURCE_ATTR).ToStringValue();

它更短,更易于阅读,并且不会违反LINQ来执行并非针对其创建的操作。

我要做的是在TestPlan类中创建一个接受类型为details的参数的构造函数?

然后只需调用testPlan = new TestPlan(details);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM