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 订阅号,获取更多最新公布!