5

My project is using EF Core 3.1, and targeting Azure Cosmos as the database.

I have an entity like this:

public class MyEntity
{
    public IEnumerable<string> Names {get;set;}
    ... other fields
}

That I would like to end up in a Cosmos document like this:

{
    "Names": ["Name1", "Name2"]
}

With the entity as is (IEnumerable<string>) I get the error:

The property 'MyEntity.Names' could not be mapped, because it is of type 'IEnumerable' which is not a supported primitive type or a valid entity type.

If I change the entity to:

public class NameEntity
{
    public string Name {get;set;}
}
public class MyEntity
{
    public IEnumerable<NameEntity> Names {get;set;}
    ... other fields
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<MyEntity>(e =>
    {
        e.OwnsMany(p => p.Identifiers);
    });
}

The document looks like this:

{
    "Id": "XXXXXX",
    "Names:" [
       {},
       {}
    ],
}

So I change the OnModelCreating:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<MyEntity>(e =>
    {
        e.OwnsMany(p => p.Identifiers, o=> o.HasKey(k=>k.Name));
    });
}

And I then get:

{
  "Names": [
    {
        "Name": "<string1>",
        "Id": "XXXX"
    },
    {
        "Identifier": "<string2>",
        "Id": "XXXX"
    }
]}

I've also looked at value converters, but I think that is more for converting property values between types, rather than converting an entity to a string.

Any help would be appreciated.

Neil
  • 11,059
  • 3
  • 31
  • 56

1 Answers1

1

Here is a similar question to yours : Entity Framework - Code First - Can't Store List<String>

Currently, it's not possible to store a list of primitive type (string included).

Your best bet would be to store the list as a string in your database, and when you fetch it you transform it back to a list.

As the link above explained it, you can do in your OnModelCreating method :

modelBuilder.Entity<YourEntity>()
        .Property(e => e.Strings)
        .HasConversion(
            v => string.Join(',', v),
            v => v.Split(',', StringSplitOptions.RemoveEmptyEntries));
Lung2019
  • 11
  • 2
  • I was explicitly told not to create a CSV :-) I did come up with a solution that involved changes to the Cosmos driver. I managed to get it working correctly for writes to Cosmos, but it was a bit hacky for reads. If I managed to make reads nicer, I might submit it as a PR. – Neil Jun 25 '20 at 15:31
  • 1
    You could use a converter from IReadOnlyCollection to string[], and it will work with CosmosDB provider, https://medium.com/@shahabganji/store-array-of-strings-with-ef-core-cosmosdb-8c69321b3983 – Saeed Ganji Mar 14 '22 at 07:14