【问题标题】:LINQ to XML Axis properties returning an attribute when selecting an element using a different attribute使用不同属性选择元素时,LINQ to XML Axis 属性返回属性
【发布时间】:2012-09-24 20:58:32
【问题描述】:

代码块四(如下)给我一个错误,我在修复方面不知所措......

这是我正在使用的 XML 架构:

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>

<!DOCTYPE ctqcfg SYSTEM "cache.dtd">

<cache version="1.0">
    <configuration name="Test">
        <cacheControl>
            <cache name="Customer" mode="off"/>
            <cache name="Vendor" mode="off"/>
            <cache name="Agency" mode="off"/>
            <cache name="Partner" mode="off"/>
        </cacheControl>
    </configuration>

    <configuration name="Production">
        <cacheControl>
            <cache name="Customer" mode="preload"/>
            <cache name="Vendor" mode="dynamic"/>
            <cache name="Agency" mode="dynamic"/>
            <cache name="Partner" mode="dynamic"/>
        </cacheControl>
    </configuration>
</cache>

XML 文件已加载

Private XElement As XElement = Nothing

Public Sub Load()
    XElement = XElement.Load(ConfigurationResource)
End Sub

当用户选择要编辑的配置时,会保留对所选配置元素根目录的引用

Private ConfigurationRoot As System.Collections.Generic.IEnumerable(Of System.Xml.Linq.XElement)

Private ConfigurationName_ As String

Public Property ConfigurationName() As String
    Get
        Return ConfigurationName_
    End Get
    Set(ByVal Value As String)
        ConfigurationName_ = Value
        ConfigurationRoot = From Configuration In XElement.<configuration> Where Configuration.@name = Value
    End Set
End Property

尝试检索与缓存名称对应的缓存模式(在本例中为客户)

Public Property CustomerCache() As String
    Get
        Try
            Return From Cache In ConfigurationRoot.<cacheControl>.<cache> Where Cache.@name = "Customer" Select Cache.@mode
        Catch Exception As Exception
            Return Nothing
        End Try
    End Get
    Set(ByVal Value As String)
        'ToDo
    End Set
End Property

我收到以下错误

System.InvalidCastException was caught
Message=Unable to cast object of type 'WhereSelectEnumerableIterator`2[System.Xml.Linq.XElement,System.String]' to type 'System.String'.

这是我使用 LINQ 的第一天,我似乎对如何访问属性有一个基本的误解——查询似乎返回了一个集合,我知道只能找到一个可能的值...

【问题讨论】:

标签: xml vb.net linq


【解决方案1】:

前三个代码块都实现了相同的结果,但访问属性内容的方法略有不同:

1。 “加密”属性的第一个(也是唯一一个)实例的直接返回:

Return "true" = (From DBConnections In Configurations.<dbConnection> Where "Customization" = DBConnections.@name Select DBConnections.<password>.@encrypted).Single

2。查询一组 XElement,然后从第一个 XElement 方法中提取“加密”属性:

Dim Element As IEnumerable(Of XElement) = (From DBConnections In Configurations.<dbConnection> Where "Customization" = DBConnections.@name Select DBConnections.<password>).Single
Return "true" = Element(0).@encrypted

前面的示例稍微误导了我们,因为 .Single 引用明确指出将找到一个且只有一个 - 但实际上我们必须处理一个集合(只有一个项目)的结果。与不需要显式处理集合来检索属性值的方法 1 相比,它更加令人困惑。

3a。查询集合中的第一个 XElement,然后提取“加密”属性方法:

Dim Element As XElement = ((From DBConnections In Configurations.<dbConnection> Where "Customization" = DBConnections.@name Select DBConnections.<password>).Single)(0)
Return "true" = Element.@encrypted

最后一个示例试图通过引用集合中的第一个项目并将其存储在其中来处理必须处理(一个项目的)集合以尽快检索集合中的项目这一误导性部分合适的类型,这样我们就可以不用担心集合,而是处理我们真正感兴趣的对象(在本例中是 XElement 对象)。

3b。更改第一个 XElement 对象中的“加密”属性

Dim Element As XElement = ((From DBConnections In Configurations.<dbConnection> Where "Customization" = DBConnections.@name Select DBConnections.<password>).Single)(0)
If Value Then
    Element.@encrypted = "true"
Else
    Element.@encrypted = "false"
End If

研究这三种查询方法有助于阐明我关于 LINQ 返回什么的心智模型。此外,我需要了解这里到底发生了什么来修改“加密”属性...

【讨论】:

    【解决方案2】:

    您需要.First().Single()

    Return (From Cache In ConfigurationRoot.<cacheControl>.<cache> Where Cache.@name = "Customer" Select Cache.@mode).First()
    

    【讨论】:

    • 谢谢,这是我需要做的。
    猜你喜欢
    • 2021-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多