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

本文关键字:更新 实体 数据 何通过 Linq-to-XML | 更新日期: 2023-09-27 18:03:19

我使用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()语句中,我无法使其工作。

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

下面应该可以工作:

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中的代码将永远不会执行。

所以,基本上,问题是,你创造了很多引入bug的可能性。

我将以以下方式实现这样的东西:

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);