【问题标题】:Querying a SQL View containing XML columns from LINQ to EF从 LINQ 到 EF 查询包含 XML 列的 SQL 视图
【发布时间】:2012-07-31 23:47:03
【问题描述】:

我在 SQL Server 2008 中创建了一个表,如下所示:

编辑:我一直在做一些设置 ANSI_NULLS OFF 和 ON 的测试,我错误地将创建表语句粘贴到 ANSI_NULLS OFF,我尝试了两种方法,但我仍然得到错误,但想修复这。希望没有其他粘贴错误。

编辑 2:我忘了指出,如果我查询原始表 (TblValues) 一切正常,则有关 ANSI_NULLS 选项的错误仅在使用 db 视图 (TblValuesView) 时发生。

SET NUMERIC_ROUNDABORT OFF;
SET ANSI_PADDING, ANSI_WARNINGS, CONCAT_NULL_YIELDS_NULL, ARITHABORT,
    QUOTED_IDENTIFIER, ANSI_NULLS ON;
GO
CREATE TABLE TblValues
(
    Context nvarchar(8) NOT NULL,
    ParentID uniqueidentifier NOT NULL,
    RowSeq int NOT NULL,
    FieldValues xml NOT NULL,
    FieldProperties xml NOT NULL,
)  ON [PRIMARY]
 TEXTIMAGE_ON [PRIMARY]

然后我将此表加载到我的数据模型中,并能够使用 LINQ to EF 对其进行查询。 FieldValues 列中的 XML 内容应如下所示:

<FieldValues>  
  <FieldValue fieldName="txtName">
    <DataType>String</DataType>
    <FldValue>field value</FldValue>
  </FieldValue>
 ...
</FieldValues>

由于我需要以更容易阅读的方式提供 xml 列中的值,因此我为此表创建了如下视图:

SET NUMERIC_ROUNDABORT OFF;
SET ANSI_PADDING, ANSI_WARNINGS, CONCAT_NULL_YIELDS_NULL, ARITHABORT,
    QUOTED_IDENTIFIER, ANSI_NULLS ON;
GO
CREATE VIEW TblValuesView
WITH SCHEMABINDING
AS
    SELECT TblValuesView.Context,
           TblValuesView.ParentID, 
           TblValuesView.RowSeq, 
           FldValue.value('(@fieldName)[1]', 'nvarchar(30)') AS FieldName, 
           FldValue.value('(DataType)[1]', 'nvarchar(13)') AS DataType, 
           FldValue.value('(FldValue)[1]', 'nvarchar(max)') AS FldValue, 
    FROM   TblValues CROSS APPLY FieldValues.nodes('/FieldValues/FieldValue') AS FldValues(FldValue)
GO  

然后我也将此视图添加到数据模型中。现在,如果我从 SQL Server Management Studio 查询此视图,我会得到正确的值:

Context |  ParentID | RowSeq | FieldName | DataType | FldValue
----------------------------------------------------------------
Ctx         <id>       1        txtName     String     Field Value

但如果执行以下 LINQ 查询:

var FldValueViewQuery = (from row in CTX.TblValuesView select row);
foreach(TblValuesView tblValue in FldValueViewQuery)
     System.Diagnostics.Trace.WriteLine(tblValue.FieldName);

然后我得到以下异常:

System.Data.EntityCommandExecutionException: An error occurred while executing the command definition. See the inner exception for details.
System.Data.SqlClient.SqlException: SELECT failed because the following SET options have incorrect settings: 'ANSI_NULLS'. 
Verify that SET options are correct for use with indexed views and/or indexes on computed columns and/or filtered indexes and/or query notifications and/or XML data type methods and/or spatial index operations.

如果我这样做,我只能从 SQL Server Mgmt 工作室得到这个错误:

SET ANSI_NULLS OFF
select * from TblValuesView

我已经搜索过 EF 是否在运行时更改了此选项,并且我已经检查了我的数据库是否启用了 ANSI_NULLS 并默认为 true。我还能检查什么?处理这种情况的资源并不多。

提前致谢!

【问题讨论】:

  • 我相信 ANSI_NULLS 将不再受支持并默认为 ON,所以无论如何你可能想摆脱它们。是否必须使用视图,或者是否允许您直接从 EF 访问 XML 内容?
  • 我也尝试过不使用 ANSI_NULLS,但它并没有真正产生影响。我需要同时做这两件事,直接从 EF 访问 XML 内容,并通过视图提供一种“简单”的方式以用于报告目的...
  • 好的,很快就会发布解决方案...为需要它的人保留视图...

标签: c# linq sql-server-2008 entity-framework sqlxml


【解决方案1】:

首先,将表按原样带入 EF,但将 FieldValues 声明为私有(getter 和 setter)。添加以下代码:

 public partial class TblValues
 {
     private XElement fldXmlValues = null;
     public XElement FieldXmlValues
     {   
        get{
           if (fldXmlValues == null){
              fldXmlValues = XElement.Parse(this.FieldValues);
              fldXmlValues.Changed += (s,e) => this.FieldValues = fldXmlValues.ToString();
           }
           return fldXmlValues;
        }
        set{
           fldXmlValues = value;
           fldXmlValues.Changed += (s,e) => this.FieldValues = fldXmlValues.ToString();
           this.FieldValues = fldXmlValues.ToString();
        }
     }
  }

那么你应该可以通过:

from t in context.TblValues
select t.FieldXmlValues.Attribute("fieldName").Value as FieldName

等等……

【讨论】:

  • 当前版本的实体框架不支持 XML 数据类型。鉴于 XML 的重要性,未来的某些版本可能会提供全面支持。
  • 我给你一个+1,因为这个答案可以作为替代方案,但我认为我的问题仍然有效,因为视图确实可以与 EF 一起使用,只有当视图必须从中提取数据时XML 类型和基于错误,我怀疑这可能是设置问题... 编辑: 结果我无法为您的帖子 +1 :((没有足够的代表)但谢谢!
【解决方案2】:

我找到了罪魁祸首。

感谢一位知道如何在我们的数据模型中设置连接的同事,我发现在打开与数据库的连接时正在执行 SET ANSI_NULLS OFF 命令,导致我们的所有命令都使用此设置运行,像这样:

public class MyConnection : DbConnection
{
    ...
    public override void Open()
    {
        using (SqlCommand cmd = new SqlCommand("SET ANSI_NULLS OFF", (SqlConnection)this.WrappedConnection))
        {
            cmd.ExecuteNonQuery();
        }
    }
    ...
}

我之所以这样做是因为 .NET 4 上的 EF 和 ANSI_NULLS 存在问题。但是像这样的查询似乎需要使用 ANSI_NULLS ON。

总之:使用 nodes() 时,包含 Xml 类型的视图在实体框架中可以工作

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-08
    • 1970-01-01
    • 1970-01-01
    • 2020-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多