Как обновить существующую сущность данными через Linq-to-XML? - PullRequest
2 голосов
/ 25 июля 2011

Я использую 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;
    }

Это меня раздражает, потому что мне нужно создать временную переменную и выполнить передачу данных.Можно ли как-нибудь обновить переменную testPlan прямо из оператора Linq, что сократит один шаг?Я не смог заставить его работать, добавив код обновления в оператор .Select().

Ответы [ 2 ]

1 голос
/ 25 июля 2011

Должно работать следующее:

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 будет содержать значения атрибута элемента last в вашем 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, чтобы делать то, для чего он не был создан.

0 голосов
/ 25 июля 2011

Что я хотел бы сделать, это создать конструктор в классе TestPlan, который принимает аргумент типа детали?

Затем просто вызовите testPlan = new TestPlan (details);

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...