5

我很难弄清楚如何在 SQL Server 中使用 xml 数据列,特别是与实体框架一起使用。

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

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

我认为 SQL Server xml 函数对此非常理想(例如, [xmlcol].exist('/path1/path2[0][text()=''valuetest'''] ),但 Entity 不支持它们框架,令人恼火(或者具体来说,不支持 xml 列)。作为替代方案,我尝试创建一个 UDF,将用户提供的 XPath 传递给 xml 函数,但后来发现 xml 函数只允许字符串文字,所以我不能提供变量...

在这一点上,我已经没有选择了。

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

我一直在寻找,偶然发现了 SQLCLR 类型的想法,并开始创建一个执行 XPath 比较的 SQLCLR 函数。我以为我在这一点上是赢家,直到一位同事指出 Azure 中的 SQL Server 不支持 SQLCLR - 哦!

我还有什么其他选择?我似乎跑得非常接近空...

4

2 回答 2

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

查询 1

exec GetIt N'*[text() = "2"]'

结果

| ID |  NAME |
--------------
|  2 | Row 2 |
于 2013-02-11T12:48:47.987 回答
0

为了保持“可定制”,可以使用DbSet 上的 SqlQuery 方法:

var query = @"SET ARITHABORT ON; 
              select * from [YourTable] where 
              [xmlcol].exist('/path1/path2[0][text()=''{0}''']";
var numOfResults = 5;
var offsetPage = 1;

var results = Context.YourTable.SqlQuery(String.Format(query,"valuetest"))
                              .OrderBy(x => x.col)
                              .Skip(offsetPage * numOfResults)
                              .Take(numOfResults).ToList();

请注意,由于其动态特性,此方法也很可能会暴露一定程度的 sql 注入安全漏洞。

于 2013-02-20T11:24:06.627 回答