使用用户提供的XPath通过实体框架查询SQL Server xml列

dar*_*ect 5 sql-server xpath entity-framework

我很难确定如何在SQL Server中使用xml数据列,特别是与Entity Framework一起使用.

基本上,我们的一个表存储用户以XML形式提供的"自定义元数据",因此将其存储在表中的Xml列中似乎是明智的.

但是,我们的应用程序的一个要求是支持搜索元数据.用户能够提供XPath查询字符串以及用于比较XPath值的值,以搜索包含与其查询匹配的元数据的元素.

我确定SQL Server xml函数是理想的(例如,[xmlcol] .exist('/ path1/path2 [0] [text()=''valuetest''']),但实体不支持它们框架,恼人地(或者特别是,不支持xml列).作为替代方案,我尝试创建一个UDF,将用户提供的XPath传递给xml函数,但后来发现xml函数只允许字符串文字,所以我无法提供变量......

此时,我的选项已经用完了.

我创建了一小段代码,在IQueryable.ToString()的结果上执行正则表达式替换,将XPath过滤器注入,然后手动将此字符串发送到数据库,但是这也存在问题,例如例如,结果似乎没有懒惰地加载导航属性.

我一直在寻找,偶然发现了SQLCLR类型的想法,并开始创建一个执行XPath比较的SQLCLR函数.我认为此时我已成为赢家,直到一位同事指出Azure中的SQL Server不支持SQLCLR - doh!

我还有其他选择吗?我好像跑得很近......

Mik*_*son 2

您可以在动态构建查询的存储过程中执行此操作。

SQL小提琴

MS SQL Server 2008 架构设置

create table YourTable
(
  ID int identity primary key,
  Name varchar(10) not null,
  XMLCol xml
);

go

insert into YourTable values
('Row 1', '<x>1</x>'),
('Row 2', '<x>2</x>'),
('Row 3', '<x>3</x>');

go

create procedure GetIt
  @XPath nvarchar(100)
as
begin
  declare @SQL nvarchar(max);

  set @SQL = N'
  select ID, Name
  from YourTable
  where XMLCol.exist('+quotename(@XPath, '''')+N') = 1';

  exec (@SQL);
end
Run Code Online (Sandbox Code Playgroud)

查询1

exec GetIt N'*[text() = "2"]'
Run Code Online (Sandbox Code Playgroud)

结果

| ID |  NAME |
--------------
|  2 | Row 2 |
Run Code Online (Sandbox Code Playgroud)