问题 XML数据类型


如何设置EF为对象使用XML的SQL数据类型?此外,如何创建SQL计算列。

我们存储了很多动态数据,有些人会在每行/每个记录中导致元数据,它不是标准的,因此我们依赖于xml数据结构,然后使用计算列来创建我们可用于更快的SQL搜索的密钥。

坦率地说 - 一个expando对象映射到xml列真的会浮动我们的船。

提前致谢。


9467
2018-04-06 16:10


起源



答案:


最初的问题是:

如何设置EF为对象使用XML的SQL数据类型?

在代码中,您可以这样做:

[Column(TypeName="xml")]
public string Foo {get; set;}

或者通过流利的api:

modelBuilder.Entity<MyEntity>()
            .Property(x => x.Foo)
            .HasColumnType("xml");

您仍然需要将该属性解释为字符串,并且您可以自己将其转换为C#中的xml。但是这样它将作为xml列生成,你仍然可以使用sql的xml函数对它执行直接的sql查询。


13
2018-01-04 14:07





您在EF中所能做的就是以字符串形式访问/读取XML列 - 从那时起,您就可以自己动手了。没有“内置”机制将XML转换为序列化对象或类似的东西。

至于计算列:

  • 您可以在SQL中定义一个简单的表达式

    ALTER TABLE dbo.YourTable
      ADD PriceWithTax AS PriceWithoutTax * (1 + TaxRate)
    

    这会给你一个新专栏 PriceWithTax 根据您的专栏 PriceWithoutTax 和另一列叫 TaxRate (0.15%的15%税)

  • 或者你可以创建一个返回单个值的存储函数,然后调用它

    ALTER TABLE dbo.YourTable
      ADD PriceWithTax as dbo.AddTaxToPrice(PriceWithoutTax, TaxRate)
    

    我们还使用存储的标量函数的这种方法来解析存储在XML列中的XML,并将某些位和片段提取到计算列中。

如果您的计算被SQL Server视为“确定性”,您还可以添加 PERSISTED 列定义的关键字。在这种情况下,您的值只计算一次并实际持久存储/存储在该表中,就像任何其他列一样。您现在甚至可以索引这些列!这适用于例如标量函数,从XML中获取位并在“父”表上公开它。


1
2018-04-06 16:24



谢谢,这解释了th侧的SQL方面,但不解释EF将创建具有XML数据类型的列的部分和/或它将如何创建post表创建表的增强,例如计算列,当我在限制等 - DougS
@DougS:也许你需要澄清一下你正在尝试做什么,你正在使用哪种EF方法(db-first,model-first,code-first)等等。 - marc_s
问题仍然存在,首先是代码,如何使用SQL列类型的XML?似乎因为它似乎不支持它检测到重大的模型更改并重建数据库。 - DougS
@DougS:你没有透露你正在与之合作 码优先 至今! - marc_s


答案:


最初的问题是:

如何设置EF为对象使用XML的SQL数据类型?

在代码中,您可以这样做:

[Column(TypeName="xml")]
public string Foo {get; set;}

或者通过流利的api:

modelBuilder.Entity<MyEntity>()
            .Property(x => x.Foo)
            .HasColumnType("xml");

您仍然需要将该属性解释为字符串,并且您可以自己将其转换为C#中的xml。但是这样它将作为xml列生成,你仍然可以使用sql的xml函数对它执行直接的sql查询。


13
2018-01-04 14:07





您在EF中所能做的就是以字符串形式访问/读取XML列 - 从那时起,您就可以自己动手了。没有“内置”机制将XML转换为序列化对象或类似的东西。

至于计算列:

  • 您可以在SQL中定义一个简单的表达式

    ALTER TABLE dbo.YourTable
      ADD PriceWithTax AS PriceWithoutTax * (1 + TaxRate)
    

    这会给你一个新专栏 PriceWithTax 根据您的专栏 PriceWithoutTax 和另一列叫 TaxRate (0.15%的15%税)

  • 或者你可以创建一个返回单个值的存储函数,然后调用它

    ALTER TABLE dbo.YourTable
      ADD PriceWithTax as dbo.AddTaxToPrice(PriceWithoutTax, TaxRate)
    

    我们还使用存储的标量函数的这种方法来解析存储在XML列中的XML,并将某些位和片段提取到计算列中。

如果您的计算被SQL Server视为“确定性”,您还可以添加 PERSISTED 列定义的关键字。在这种情况下,您的值只计算一次并实际持久存储/存储在该表中,就像任何其他列一样。您现在甚至可以索引这些列!这适用于例如标量函数,从XML中获取位并在“父”表上公开它。


1
2018-04-06 16:24



谢谢,这解释了th侧的SQL方面,但不解释EF将创建具有XML数据类型的列的部分和/或它将如何创建post表创建表的增强,例如计算列,当我在限制等 - DougS
@DougS:也许你需要澄清一下你正在尝试做什么,你正在使用哪种EF方法(db-first,model-first,code-first)等等。 - marc_s
问题仍然存在,首先是代码,如何使用SQL列类型的XML?似乎因为它似乎不支持它检测到重大的模型更改并重建数据库。 - DougS
@DougS:你没有透露你正在与之合作 码优先 至今! - marc_s


虽然不是您正在寻找的答案,但NHibernate完全支持您正在处理的场景。两种方法:

  • 用一个 XDocument 要么 XmlDocument 您的域模型中的属性。它开箱即用,您可以将其映射到 xml sql类型, nvarchar(max)
  • 使用自定义类型用xml列做任何你需要的魔法(包括mpping到动态对象,值类型,字典或任何你可以梦想的东西)

此外,对于一般的计算属性,您可以查看 formula 和 readonly

如果您在项目中处于足够早的阶段并需要这种灵活性,则可以考虑进行切换。


1
2018-04-09 12:30