EF Core 6.0在往年的11月曾经正式公布了。团队的成员们始终在致力增加并欠缺性能。其中一个重点畛域是Azure Cosmos DB体验。咱们收到的反馈是,许多开发人员更违心应用Cosmos DB,但仍在期待某些要害性能。

行星文档

我在Blazor服务器上创立了一个应用Azure Cosmos DB 和EF Core的扩大程序。它包含搜寻性能、穿插援用实体以及一个能够新建、读取和更新的接口。我最近降级到最新的EF Core 6.0版本,并可能简化和删除相当多的代码!

性能概述

以下是咱们在EF Core 6.0 Azure Cosmos DB provider中增加的一些个性。

隐式的所有权

EF Core被构建成一个对象关系映射器。在关系数据库中,简单的关系是通过将相干实体存储在独自的表中并应用外键援用它们来示意的。EF Core假设在父类中遇到的非实体类型被示意为外键关系。应用HasMany或HasOne配置关系,并且假如实例与配置的关系独立存在。在文档数据库中,实体类型的默认行为是假设它们是父类所领有的嵌入式文档。换句话说,简单类型的数据存在于父类型的上下文中。在晚期版本的EF Core中,必须显式地配置此行为,使其可能与Azure Cosmos DB provider一起工作。在EF Core 6.0中,所有权是隐性的。这将保留配置并确保行为与其余提供者的NoSQL办法统一。

例如,在行星文档中有作者和标签。这些实体“领有”一个指向URL和相干文档题目的摘要列表。这样,当用户问“什么文档有标签X”时,我只须要加载一个文档来答复这个问题(我加载标签X,而后迭代它领有的题目汇合)。应用EF Core5,我必须明确申明所有权:

tagModel.OwnsMany(t => t.Documents);authorModel.OwnsMany(t => t.Documents);

在EF Core 6中,所有权是隐式的,所以除了指定分区键外,不须要配置实体。

反对原始汇合

在关系数据库中,原始汇合的建模办法通常是将它们晋升为简单类型,或者将它们转换为可序列化的货色以存储在单个列中。比方有一篇博客,它能够有很多标签。一种常见的办法是创立一个代表标签的实体:

public class Tag {    public int Id { get; set; }    public string Text { get; set; }}

而后标签类被援用:

public ICollection<Tag> Tags { get; set; }

接着原始类型被晋升为简单类型并存储在一个独自的表中。另一种办法是将标签组合成一个字段,该字段蕴含一个以逗号分隔的列表。这种办法须要一个值转换器将列表编组到字段中以进行更新,并将字段合成为列表以进行读取。这也使得答复诸如“有多少贴子有X标签?”这样的问题变得艰难。在应用EF Core 5时,我抉择了单列办法。我在写入时将列表序列化为JSON,在读取时将其反序列化。这是序列化代码:

private static string ToJson<T>(T item) => JsonSerializer.Serialize(item);private static T FromJson<T>(string json) => JsonSerializer.Deserialize<T>(json);

我配置EF Core来进行转换:

docModel.Property(d => d.Tags)

.HasConversion(    t => ToJson(t),    t => FromJson<List<string>>(t));

后果文件看起来是这样的:

{    "tags" : "[\"one\", \"two\", \"three\"]"}

在EF Core 6.0中,我只是删除了代码而后利用原始类型的内置解决形式,后果是这样的文档:

{    "tags" : [         "one",        "two",        "three"    ]}

这导致了schema发现扭转,然而Azure Cosmos DB没有问题解决。另一方面,当应用标签作为数组的以后模型遇到应用标签作为字段的旧记录时,c#代码将抛出异样。当EF Core没有NoSQL迁徙的概念时,咱们如何解决这个问题?

Raw SQL

一个很常见的申请是容许开发人员为数据拜访编写本人的SQL。这正是我解决代码迁徙所须要的个性。要使Raw SQL工作,它必须投射到一个现有的模型。它是实体的DbSet<T>的扩大。在我的例子中,它反对就地迁徙。在更新代码之后,尝试加载文档将会失败。文档只有一个字符串属性用于“tag”,但c#模型是一个数组,因而JSON序列化会抛出一个异样。为了解决这个问题,我应用了Azure Cosmos DB的一个内置个性,它将字符串解析为数组。应用查问,我将实体投影到匹配以后schema的文档中,而后将其保留回来。这是迁徙代码:

var docs = await Documents.FromSqlRaw(    "select c.id, c.Uid, c.AuthorAlias, c.Description, c.Html, c.Markdown, c.PublishDate, c.Title, STRINGTOARRAY(c.Tags) as Tags from c").ToListAsync();foreach (var doc in docs){    Entry(doc).State = EntityState.Modified;}

这个个性使开发人员可能创立LINQ provider可能不反对的简单查问。

其余加强性能

除了我曾经介绍过的内容之外,这些加强性能也蕴含在其中。

  • 对于多对多关系,EF Core当初隐式地在连贯类型上应用分区键
  • 您能够在实例、类型和汇合级别为文档配置生存工夫(TTL)
  • 您能够配置容器个性,如吞吐量、大小等 通过EF Core APIs。
  • 咱们当初记录特定于Cosmos DB的诊断事件,包含查问老本。
  • 咱们在查问中增加了对DISTINCT操作符的反对
  • LINQ provider当初将某些办法(如字符串操作和数学操作)转换为它们的原生Cosmos DB对应办法

总结

我对行将到来的变动感到兴奋,心愿你们也一样。你正在应用Cosmos DB provider吗? 如果还没有,在咱们增加了以上性能之后你违心应用吗? 或者还有更多需要和倡议,请在本文上面留言,谢谢!


欢送关注微软中国MSDN订阅号,获取更多最新公布!