Entity Framework delete and modify using guid and EntityState - entity-framework

I'm using Entity Framework to handle data transactions and we have a user entity which had a primary key type integer named ID.
In our SQL Server the Identity specification was set to Yes, Is Identity also set to yes with an auto increment of 1.
To delete a user, I used this code:
ctx.Users.Attach(user);
ctx.Entry(user).State = EntityState.Deleted;
ctx.SaveChanges();
However, we have changed our user entity to have a Guid as a primary key:
public class User
{
DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public Guid ID { get; set; }
public string Username { get; set; }
}
In the database, it is set to data type uniqueidentifier with a "Default Value or Binding" set to (newsequentialid())
After changing this, the Entity Framework code to delete a user throws the following error:
Attaching an entity of type 'Administration.Model.User' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.
Why is it throwing this error? I suppose it has something to do with the way the primary key is generated, but how can I fix this?
Of course, I could use a linq query and use .Remove, but I want to keep the solution I had using an int value as primary key.

Related

key by navigation property using annotation (entity framework)

I have a class as
public class fooClass
{
[Key]
public virtual fooRefClass staff { get; set; }
public Int64 fooProp1{ get; set; }
public DateTime fooProp2{ get; set; }
}
when i do the migration it give me error as "no key defined" but i had added the key attonation already .My intention is to make the referenced entity "fooRefClass " as primary key as well as foreign key, i know there is a way by mentioning the attribute id of the referenced entity and writing the foreign-key annotate over there, but i want to deal with entity directly ,rather than id only, how can i attain this functionality ,please help me with the issue.
Since there seems to be confusion, I decided to write an answer as well.
With the class you defined, EF would expect a table like
fooClass(bigint fooRefClass_Id, bigint fooProp1, datetime fooProp2);
... which is not valid, because this has no key column (the key annotation on your navigation property does nothing, because you see, it won't appear in the table... it will just tell EF there is a relationship to this table, and because you didn't provide a FK, it creates one to create this relationship). You also can't create this relationship yourself in your current model, because you don't even have a FK... how would you access a property you know nothing about, just that it will be created at some point (usually upon model creating with first accessing the database).
You have to tell EF you want the property, that will be created, to also be a key, not only a foreign key. You can do this by simply creating the property yourself and telling EF you want to use this, for example (I'm not too familiar with Data Annotations, I usually use Fluent API, so please excuse maybe occuring errors)
[Key, Foreign Key(fooRefClass)]
public Int64 StaffId {get; set;}

How to alter relationship keeping existing data in entity framework code first?

I have two entities
public class Account
{
[Key]
public int Id { get; set;
public int MemberInfoId { get; set; }
public Member MemberInfo { get; set; }
//Other Properties
}
public class Member
{
[Key]
public int Id { get; set; }
//Other Properties
}
With following relationship
modelBuilder.Entity<Account>()
.HasRequired(a => a.MemberInfo)
.WithMany()
.HasForeignKey(a => a.MemberInfoId)
.WillCascadeOnDelete(true);
However, an Account has one Member only so the following relation is better suited (I guess)
modelBuilder.Entity<Account>()
.HasRequired(a => a.MemberInfo)
.WithRequiredPrincipal()
.WillCascadeOnDelete(true);
But code first migration won’t migrate to that. It gives the following error
The object 'PK_dbo.Members' is dependent on column 'Id'.
The object 'FK_dbo.Accounts_dbo.Members_MemberInfo_Id' is dependent on column 'Id'.
ALTER TABLE DROP COLUMN Id failed because one or more objects access this column.
What can I do to alter the relation without recreating the database to keep the already inserted data?
First, you can read this page on mixing code-based migrations with automatic migrations to see if you even want to go this route in the first place. Generally, it's not a good idea if you have a team involved.
Next, it might be good to know that if you change the relationship between Member and Account to a one-to-one, Entity Framework requires that the primary key on the dependent side also be the foreign key. The column that used to be the primary key on the dependent side will become useless from EF's perspective. You also won't need the Account.MemberInfoId anymore, either.
Finally to create a migration, after you finish modifying the models, you can run Add-Migration with a migration name. This will create a migration file with a DbMigration class that you can modify. You'll probably need to do something like the following:
Create a new column in Member that will hold the new foreign key
Use Sql() to update values in that column with the primary key of the associated account
Drop the foreign key constraint, index, and primary key
Drop the account.memberinfo_id column and member.id column (which is optional, but if you don't drop the member.id column, you'll have to make sure to map the model's Member.Id property to the column created above).
Rename new column in member to id
Add primary key to new column in Member
Add index and foreign key
I'm sure I've missed something, but that's the general gist. I'd probably also backup everything, since something's guaranteed to go wrong the first five times or so.

EF FluentAPI how to make navigation property accessible by either object or Id

I have a POCO User that has a Company property.
When create a User in WebAPI I would like to just set the Company_Id that I am getting passed in json in the request and not have to load the Company entity from the database context in order to set it in the User.
I tried adding a User.Company_Id property in addition to the User.Company property and migrations ends up creating a Company_Id1 column in my database.
you should use Forign key attribute to let EF know it's a foreign key.
public class User
{
[ForeignKey("Company_Id")]
public Company Company {get;set;}
public int Company_Id {get;set;}
}

How to prevent Code First from enabling foreign key constraint on a relationship?

I have two entities, User and Feedback, and there is one-to-many relationship between those with help of the username field.
Feedback --> User
-------- --------
username username
However, sometimes feedback may code from an unregistered user, and Username field on Feedback will be Null. In that case, the addition of feedback will fail due to the foreign key constraint.
How can I disable the enforcement of a foreign key constraint on a relationship declaratively or by means of the Fluent API? It is enabled by default when the DB is created.
Thank you!
You don't need to disable the enforcement of the foreign key constraint for your purpose, you just need to allow NULL values for the foreign key which is called an optional one-to-many relationship (in contrast to a required relationship which doesn't allow NULL values of the foreign key).
You can define this optional relationship the following way:
public class Feedback
{
public int Id { get; set; }
[ForeignKey("User")]
public int? UserId { get; set; }
public User User { get; set; }
}
Having a nullable type int? for the foreign key makes the relationship optional. If User has a primary key property named Id you can even omit the [ForeignKey] attribute because Entity Framework will detect UserId as the foreign key of the User navigation property based on naming conventions.
Alternatively instead of data annotations you can use Fluent API:
modelBuilder.Entity<Feedback>()
.HasOptional(f => f.User)
.WithMany() // or WithMany(u => u.Feedbacks)
.HasForeignKey(f => f.UserId);

Entity Framework inserting row with composite key

I am using Entity Framework 4.3.1 and I am trying to insert a new record into the table my ProductVersion entity is based on.
The ProductVersion entity has 2 properties that make up a composite primary key for the table called ProductId and ProductOrdinal.
Whenever someone updates a product entry I am creating and passing a ProductVersion entity back to my repository, incrementing the ProductOrdinal property, and attempting to add the entity to the context and save it.
I keep getting the following error:
The property 'ProductOrdinal' is part of the object's key information and cannot be modified.
Neither of the columns that make up the key are autonumbering and I have annotated the properties in my POCO with the following:
[Key, Column("PROD_Ordinal", Order=2), DatabaseGenerated(DatabaseGeneratedOption.None)]
public long ProductOrdinal { get; set; }
Marc_S was exactly right in his comment as to why this was not working.
From the exception and your description it seems that you are incrementing the 'ProductOrdinal' property on the existing 'ProductVersion' instance and trying to save it. What you probably want to do is create a new instance of 'ProductVersion' from the existing instance and increment the 'ProductOrdinal' property and save the new instance.