9
votes

I've been struggling with changing values in a database for a week and can't find out what I'm doing wrong. I managed to create tables, to add and delete entities but I can't change a value inside an entity.

The error I get is: The property 'Rating' on entity type 'Generation' is part of a key and so cannot be modified or marked as modified. To change the principal of an existing entity whith an identifying foreign key first delete the dependent and invoke 'SaveChanges' then associate the dependent with the new principal.

(I'm not used to the term principal but I think it is the entity which has the unique Key. I not used to the term dependent either in a database context but I think it is the entity in another table which has a link to the principal)

FYI: I'm using Microsoft.AspNetCore.All 2.0.0, Microsoft.EntityFrameworkCore 2.0.0 and Npgsql.EntityFrameworkCore.PostgreSQL 2.0.0

I'm sure this error message tries to tell me the solution but as far as I know there is nothing dependent on Rating and it's not a key. For context here are the two classes I'm using for tables in the database:

[Table("Generation")]
public class Generation
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int GenerationId { get; set; }

    [Required]
    [MaxLength(100)]
    public string DNA { get; set; }
    //[Editable(true)]
    public double Rating { get; set; }

    public Generation(int ID, string dna, double rate)
    {
        GenerationId = ID;
        DNA = dna;
        Rating = rate;
    }

    public Generation()
    {

    }
}

[Table("Device")]
public class Device
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int DeviceID { get; set; }

    //[Required]
    [MaxLength(100)]
    public string Identifier { get; set; }

    //[ForeignKey("GenerationId2")] <-- should be changed to GenerationId in the near future
    public int GenerationId2 { get; set; }
    public float WaitingSeconds { get; set; }
}

(It's a database I want to keep on a server for genetic algorithms)

The code I use to change the data is quite simple but causes the error on SaveChanges():

Generation gen = Program.Context.Generation.FirstOrDefault(g => g.Rating < 0.0);
if (gen != null)
{
gen.Rating = 10.0;
Debug.Log("DNA: About to save changes");
Program.Context.SaveChanges();
}

(The generations are created with a negative rating to indicate that that DNA has not been tested yet)

I experimented with different data annotations such as [Editable(true)], [Required] and [ForeignKey] <- which I suppose marks it as dependent on the principal from another class/table.

Could someone help me out to "simply" change some data in a table?

Kind regards!

Cambesa

2
but causes the error on SaveChanges() What's the error? Please add that to your post. - penleychan
Check your db table, is "rating" a primary key? - mxmissile
The error is in the post, the 2nd paragraph - Cambesa
mxmissile, thanks for the hint, I just found out everything is a primary key. (marked as [PK]) How would I go about marking only the GenerationId as primary key if the [Key] data annotations has no effect? The MaxLength does work because it shows the maximum length is 100 - Cambesa
@Cambesa Is there some fluent API configuration in your code which is using HasKey (...) method? - Ivan Stoev

2 Answers

5
votes

In my OnModelCreating method I was using HasKey which changed everything to primary keys.

By replacing:

protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Generation>().HasKey(g => new { { g.DNA, g.GenerationId, g.Rating } });
    }

with:

protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Generation>().HasKey(g => new { g.GenerationId });
        }

It marks only the generation id as primary key, the other variables are now editable.

Thanks Ivan Stoev

0
votes

I was getting this error for a different use case. The HasKey thing was not the problem for me.

I was writing some code to get an object graph from one database and migrate it to another database (same schema). I was clearing GUID Id values in the object, so it would get inserted in the destination DB. This did not make Entity Framework happy and I go the error:

To change the principal of an existing entity with an identifying foreign key, first delete the dependent and invoke 'SaveChanges', and then associate the dependent with the new principal.

So to fix this, I cleared all the Ids in the object graph first. Then Attach the object to the DbContext. Then I can modify state and call SaveChanges.

The trick is to not modify Ids while Entity Framework is tracking something.