1
头图

EF Core 6.0 has been officially released in November this year. The members of the team have been working hard to add and improve features. One of the key areas is Azure Cosmos DB experience . The feedback we received is that many developers prefer to use Cosmos DB, but are still waiting for certain key features.

Planetary Document

Azure Cosmos DB and EF Core on the Blazor server. It includes search functions, cross-reference entities, and an interface that can be created, read, and updated. I recently upgraded to the latest EF Core 6.0 version and was able to simplify and remove quite a lot of code!

ae9f6503cd125a08da226dc24fafc4b5.png

function overview

The following are some of the features we added in EF Core 6.0 Azure Cosmos DB provider.

implicit ownership

EF Core is built as an object-relational mapper. In relational databases, complex relationships are represented by storing related entities in separate tables and referencing them using foreign keys. EF Core assumes that the non-entity types encountered in the parent class are represented as foreign key relationships. Use HasMany or HasOne to configure the relationship, and assume that the relationship between the instance and the configuration exists independently. In a document database, the default behavior of entity types is to assume that they are embedded documents owned by the parent class. In other words, data of a complex type exists in the context of the parent type. In earlier versions of EF Core, this behavior must be explicitly configured to enable it to work with the Azure Cosmos DB provider. In EF Core 6.0, ownership is implicit. This will save the configuration and ensure that the behavior is consistent with the NoSQL approach of other providers.

For example, there are authors and tags planetary documents These entities "own" a summary list of URLs and related document titles. In this way, when the user asks "what document has tag X", I only need to load a document to answer this question (I load tag X, and then iterate over the set of titles it has). With EF Core5, I must clearly declare ownership:

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

In EF Core 6, ownership is implicit, so there is no need to configure entities other than specifying the partition key.

supports the original collection

In relational databases, the modeling method of primitive collections is usually to promote them to complex types, or convert them into serializable things to be stored in a single column. For example, if there is a blog, it can have many tags. A common method is to create an entity that represents the label:


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

Then the label class is referenced:

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

Then the original type is promoted to a complex type and stored in a separate table. Another method is to combine the tags into a field that contains a comma-separated list. This method requires a value converter to marshal the list into fields for updating, and decompose the fields into lists for reading. This also makes it difficult to answer questions such as "How many posts have X tags?" When using EF Core 5, I chose the single-column approach. I serialize the list to JSON when writing, and deserialize it when reading. This is the serialization code:

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

I configure EF Core to perform the conversion:

docModel.Property(d => d.Tags)

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

The resulting file looks like this:

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

In EF Core 6.0, I just deleted the code and used the original type's built-in processing method, the result is this document:


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

This caused the schema to find changes, but Azure Cosmos DB did not deal with the problem. On the other hand, when the current model that uses tags as an array encounters old records that use tags as fields, the c# code will throw an exception. How do we deal with this problem when EF Core does not have the concept of NoSQL migration?

Raw SQL

A very common request is to allow developers to write their own SQL for data access. This is exactly the feature I need to handle code migration. For Raw SQL to work, it must be projected to an existing model. It is an extension of the entity's DbSet<T>. In my case, it supports in-place migration. After updating the code, attempts to load the document will fail. The document has only one string attribute for "tag", but the c# model is an array, so JSON serialization will throw an exception. To solve this problem, I use a built-in feature Azure Cosmos DB, it will be the word string parsing an array . Using a query, I project the entity into a document that matches the current schema, and then save it back. This is the migration code:

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;
}

This feature enables developers to create complex queries that may not be supported by the LINQ provider.

Other enhancements

In addition to what I have already introduced, these enhancements are also included.

summary

I am excited about the upcoming changes, and I hope you are the same. Are you using the Cosmos DB provider? If not, would you like to use it after we added the above features? Or if you have more needs and suggestions, please leave a message below this article, thank you!


Welcome to follow the Microsoft China MSDN subscription account for more latest releases!
image.png


微软技术栈
423 声望996 粉丝

微软技术生态官方平台。予力众生,成就不凡!微软致力于用技术改变世界,助力企业实现数字化转型。