Tobias Moe Thorstensen
Tobias Moe Thorstensen

Reputation: 8981

Updating entities with Entity Framework and cosmos db

During the

_dbContext.Update(entity)

The following exceptions occurs:

System.InvalidOperationException: 'Unable to track an entity of type 'User' because alternate key property 'id' is null. If the alternate key is not used in a relationship, then consider using a unique index instead. Unique indexes may contain nulls, while alternate keys must not.'

Looking into the way I've configured the DbContext:

modelBuilder.Entity<User>().HasKey(p => p.Id);

Running the following sql command in cosmos emulator, returns the correct entity:

SELECT * FROM c where c.Id="My-Guid-Id"

How can I update an existing entity using Entity Framework as ORM and Cosmos as my database provider?

Upvotes: 0

Views: 4713

Answers (2)

T.J. McNaboe
T.J. McNaboe

Reputation: 59

From the docs: "Working with disconnected entities Every item needs to have an id value that is unique for the given partition key. By default EF Core generates the value by concatenating the discriminator and the primary key values, using '|' as a delimiter. The key values are only generated when an entity enters the Added state. This might pose a problem when attaching entities if they don't have an id property on the .NET type to store the value. To work around this limitation one could create and set the id value manually or mark the entity as added first, then changing it to the desired state:"

https://learn.microsoft.com/en-us/ef/core/providers/cosmos

Upvotes: 1

Jack Jia
Jack Jia

Reputation: 5549

I tested at my side, however everything was fine at my side.

My code:

Item.cs

For reproducing your issue, I use "ID" instead of "id"

    public class Item
    {
        public Item(string key, string content) => (this.key, this.content) = (key, content);

        public string ID { get; set; } = Guid.NewGuid().ToString();

        public string key { get; set; }

        public string content { get; set; }
    }

CosmosDBContext .cs

    public class CosmosDBContext : DbContext
    {
        public CosmosDBContext(DbContextOptions<CosmosDBContext> options) : base(options)
        {

        }

        public DbSet<Item> Items { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            // Set partition key, set container
            modelBuilder.Entity<Item>().ToContainer("JackTest");
            modelBuilder.Entity<Item>().HasKey("ID");
            modelBuilder.Entity<Item>().HasPartitionKey("key");
        }
    }

Create one item:

    _cosmosDBContext.Items.Add(new Item("aaa", "abcdefg"));
    _cosmosDBContext.SaveChanges(true);

From the data explorer, we can see that the item was created:

enter image description here

And we can see that system will generate the default "id".

Update item

    var item = _cosmosDBContext.Items.Where(i => i.content.Equals("abcdefg")).FirstOrDefault();
    item.content = DateTime.Now.ToString("yyyy-MM-ddThh:mm:ss.fffZ") + item.content;
    _cosmosDBContext.Update(item);
    _cosmosDBContext.SaveChanges(true);

And the item was updated:

enter image description here

Upvotes: 3

Related Questions