Efcore: Cosmos Driver doesn't store read only owned properties

Created on 22 Jun 2020  路  2Comments  路  Source: dotnet/efcore

When an entity has a child property, that is set to be owned (and therefore should be included in the body of the json serialised to the Cosmos document), and the setter property(s) of the child object are missing (constructor only), then when serialising to Cosmos, the child properties are not serialised.

public class TestItem
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public IEnumerable<TestIdentifier> Identifiers { get; set; }
}
public class TestIdentifier
{
    public string Identifier { get; /*private set; */} <-- This is the problem line

    public TestIdentifier()
    {
    }

    public TestIdentifier(string identifier)
    {
        Identifier = identifier;
    }
}
public class TestItemEntityTypeConfiguration : IEntityTypeConfiguration<TestItem>
{
    public void Configure(EntityTypeBuilder<TestItem> builder)
    {
        builder.ToContainer("testItems");
        builder.HasPartitionKey(k => k.Name);
        builder.OwnsMany(o => o.Identifiers);
    }
}

Steps to reproduce

Using the above entities, the document stored in Cosmos is :

{
    "Id": "b1911b62-0ad0-475b-8b7c-40f8466c241e",
    "Discriminator": "TestItem",
    "Name": "Test1",
    "id": "TestItem|b1911b62-0ad0-475b-8b7c-40f8466c241e",
    "Identifiers": [
        {},
        {}
    ],
    "_rid": "5WRwAKHTkF0IAAAAAAAAAA==",
    "_self": "dbs/5WRwAA==/colls/5WRwAKHTkF0=/docs/5WRwAKHTkF0IAAAAAAAAAA==/",
    "_etag": "\"00000000-0000-0000-4894-73f191ed01d6\"",
    "_attachments": "attachments/",
    "_ts": 1592830549
}

Notice how the Identifier properties are empty {}.
If TestIdentifier.Identifier has a private or public setter, then it serialised correctly.

Not sure why a serialisation would depend on a setter. (Deserialisation is obviously a different matter).

Further technical details

EF Core version: 3.1.5
Database provider: Cosmos driver 3.1.5
Target framework: NET Core 3
Operating system: Windows 10
IDE: Visual Studio 2019 16.2.2

closed-question customer-reported

Most helpful comment

@Soundman32 Read-only properties are not mapped by default. This can be overridden by explicitly mapping the property:

C# builder.OwnsMany(o => o.Identifiers, b => { b.Property(e => e.Identifier); });

All 2 comments

My guess would be there is a CanWrite where a CanRead would be correct.

@Soundman32 Read-only properties are not mapped by default. This can be overridden by explicitly mapping the property:

C# builder.OwnsMany(o => o.Identifiers, b => { b.Property(e => e.Identifier); });

Was this page helpful?
0 / 5 - 0 ratings