ojek
ojek

Reputation: 10078

EF Code First Modelbuilder creating unique identifiers where it should not

I have something like this:

modelBuilder.Entity<TransactionHistory>()
                .HasOptional(history => history.Sender)
                .WithMany()
                .Map(s => s.MapKey("Sender"))
                .WillCascadeOnDelete(false);

modelBuilder.Entity<TransactionHistory>()
                .HasOptional(history => history.Receiver)
                .WithMany()
                .Map(s => s.MapKey("Receiver"))
                .WillCascadeOnDelete(false);

And in my table TransactionHistory, it creates unique identifiers at columns Sender and Receiver. I don't want those columns to be unique, what do i do?

TransactionHistory model:

public class TransactionHistory
    {
        public Account Sender { get; set; }
        public Account Receiver { get; set; }
    }

Edit: Ok. Apparently uniqueidentifiers are not the case. The problem is, that when i am adding transactionhistory item into database, i got the following error:

Violation of PRIMARY KEY constraint 'PK_dbo.Accounts'. Cannot insert duplicate key in object 'dbo.Accounts'.\r\nThe statement has been terminated.

An i add this item like that:

context.Transactions.Add(history);
context.savechanges();

(Transactions is a transactionhistory object)

Upvotes: 1

Views: 591

Answers (2)

Ben Tidman
Ben Tidman

Reputation: 2139

Entity framework works by storing a cache of a bunch of objects in DBContext. Even if all the properties are the same on your Account object (including your pk) entity framework will see this as a new object unless you remind it "hey, you already know about this". I can think of 2 ways to do this:

context.Entry(history.Sender).State = EntityState.Modified; 
context.Entry(history.Receiver).State = EntityState.Modified; 

or

Make sure when you set the Accounts on your history object that they are already attached to your dbcontext.

var sender = context.Accounts.FirstOfDefault(...your condition here...);
var receiver = context.Accounts.FirstOfDefault(...your condition here...);

history.Sender = sender;
history.Receiver = receiver;

Also EF does not load navigation/related entities unless you tell it to. So if you are editing history make sure you using .Include() to pull in your related objects.

Hope that helps.

Upvotes: 1

Slauma
Slauma

Reputation: 177163

EF uses uniqueidentifier as SQL column type for the foreign keys because the principal's (= Accounts) primary key is a uniqueidentifier - in C# it is a Guid, like public Guid AccountId { get; set; }.

It must choose this type because principal and dependent key types must match in a foreign key relationship in the database.

This does not mean that the foreign key column is unique (or has a unique index). Of course you can use the same uniqueidentifier value multiple times as the foreign key column value.

Upvotes: 2

Related Questions