为什么不能将 LINQ to XML 与 LINQ to SQL 结合起来

本文关键字:LINQ to SQL 结合 起来 XML 不能 为什么 | 更新日期: 2023-09-27 18:31:56

我有这段代码:

var xml = XDocument.Load(filePath);
var taxReturns = (from t in xml.Descendants("aangiftes").Elements()
    where t.Name == "ib"
    select new Domain.TaxReturn
    {
        FiscalNumber = t.Attribute("sofinr").Value,
        Guid = Guid.Parse(t.Attribute("guid").Value),
        LastFormOpen = t.Attribute("lastformview").Value,
        Name = string.Empty, 
        TaxYear = t.GetAttributeValue<short>("belastingjaar"),
        TaxForm =  unitOfWork.TaxForms.FirstOrDefault(tf => tf.Code == t.Attribute("biljetsoort").Value),
    }).ToArray();

当我运行此代码时,我收到以下异常:

LINQ to Entities 无法识别方法 System.Xml.Linq.XAttribute Attribute(System.Xml.Linq.XName)-method,并且此方法无法转换为存储表达式

但是,当我将此行提取到方法中时,它工作正常。

有人可以解释这种行为吗?我不明白这种行为:/

为什么不能将 LINQ to XML 与 LINQ to SQL 结合起来

这是因为 LINQ 尝试将Domain.TaxReturn {...}中的代码编译为 SQL。SQL 中没有相应的 API 用于XElement.Attribute(...)因此会失败。

尝试将XElement依赖代码移出Domain.TaxReturn {...}
喜欢这个:

var xml = XDocument.Load(filePath);
var taxReturns = (from t in xml.Descendants("aangiftes").Elements()
    where t.Name == "ib"
    let sofinr = t.Attribute("sofinr").Value
    let guid = Guid.Parse(t.Attribute("guid").Value)
    let lastformview = t.Attribute("lastformview").Value
    let belastingjaar = t.GetAttributeValue<short>("belastingjaar")
    let biljetsoort = t.Attribute("biljetsoort").Value
    select new Domain.TaxReturn
    {
        FiscalNumber = sofinr ,
        Guid = guid,
        LastFormOpen = lastformview,
        Name = string.Empty, 
        TaxYear = belastingjaar,
        TaxForm = unitOfWork.TaxForms.Single(tf => tf.Code == biljetsoort),
    }).ToArray();

(未经测试)

另外,您可能想使用Enumerable.Single而不是Enumerable.FirstOrDefault,或者null是一个有效的案例?

正如文档中所说 -

当应用程序运行时,LINQ to SQL 会将对象模型中的语言集成查询转换为 SQL,并将其发送到数据库执行

http://msdn.microsoft.com/en-us/library/bb386976%28v=vs.110%29.aspx

仔细检查执行顺序,"先生成 SQL 后执行"

你可以很容易地理解为什么会发生这种情况。在 SQL 中没有替代System.Xml.Linq.XAttribute Attribute(System.Xml.Linq.XName)

例如,.OrderBy()具有 SQL 等效order by,因此当 LINQ 看到此方法时,它会将其转换为 order by 并执行查询。但是当 linq 看到 System.Xml.Linq.XAttribute Attribute(System.Xml.Linq.XName) 时,没有 SQL 等效项,LINQ 抛出一个错误,说它无法识别它。

但是,当您将该行提取到方法中时,将首先执行该方法,因此此时 LINQ to SQL 已经工作了,并且您要查找的所有实体都已包含在 RAM 中,现在您可以执行任何 LINQ to XML。这次查询不会转换为 SQL,因为实体已经作为托管对象在 RAM 中,并且您的代码工作正常。