Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Identity column in EF 4

I follow by entity framework example :

http://msdn.microsoft.com/en-us/library/bb399182.aspx

and I have problem with Identity Columns.

Here is part of code of creating database:

CREATE TABLE [dbo].[Person](
    [PersonID] [int] IDENTITY(1,1) NOT NULL,
    [LastName] [nvarchar](50) NOT NULL,
    [FirstName] [nvarchar](50) NOT NULL,
    [HireDate] [datetime] NULL,
    [EnrollmentDate] [datetime] NULL,
 CONSTRAINT [PK_School.Student] PRIMARY KEY CLUSTERED 
(
    [PersonID] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO

In VS 2010 I build .edmx and at model I see that Person StoreGeneratedPattern is set to Identity.

But when I want to create Person, by : alt text

Why I must put id, if this column is autoincrement?

EDITŁ

I thought that I found the way to resolve my problem by:

var schoolContext = new SchoolEntities();

            schoolContext.AddToPeople(new Person() { LastName = "Gates", FirstName = "Bil" });

            schoolContext.SaveChanges();

because it added Bill to persons, but...because PersonID is not nullable, and it inserted him with id 0. When I tried add another person the same way of course I get error about primary key :)

So still with nothing...

Any ideas ?

like image 510
user278618 Avatar asked Sep 04 '10 11:09

user278618


People also ask

What are identity columns?

Identity columns can be used for generating key values. The identity property on a column guarantees the following: Each new value is generated based on the current seed & increment. Each new value for a particular transaction is different from other concurrent transactions on the table.

How do I get identity value in EF core?

EF execute each INSERT command followed by SELECT scope_identity() statement. SCOPE_IDENTITY returns the last identity value inserted into an identity column in the same scope. The above example will execute the following SQL in the database. WHERE @@ROWCOUNT = 1 AND [StudentID] = scope_identity();

Is identity column a primary key?

An identity column differs from a primary key in that its values are managed by the server and usually cannot be modified. In many cases an identity column is used as a primary key; however, this is not always the case.


1 Answers

IMO the Id is needed even if it is generated. Suppose that you are using Foreign Key association (different behavior than independent association). It means that related child entities are using primary key of the parent entity to build relation. Now suppose that you are adding multiple parent entities with related entities in single unit of work. You have to specify unique (temporary) Id for each parent entity otherwise you will never configure your object graph. So the code generator probably makes this as default.

Edit:

I'm surprised that I have been downvoted for answer based on correct facts. So let me clarify my answer:

There are two types of relations available in EF 4.0. Independent association and Foreign key association. The diference is that the later one adds foreign key properties to entities. This allow you to work with relations in the same way as in database - simply by setting keys. You can read about these diferences in MSDN.

Now lets assume simple example. I have simple EDMX model with MyContext. Model consists of two entities Order and OrderLine. When I added Orders and OrderLines tables to the model I thicked Include foreign keys columns in model so I'm using Foreign keys associations instead of independent associations.

Order has store generated Id as a key and CustomerName as a property. Order line has store generated Id as a key, ProductTitle as property and OrderId as foreign key. I want to add two orders in single unit of work:

using (var context = new MyContext())
{
  var ox = Order.CreateOrder(0, "CustomerX");
  var oy = Order.CreateOrder(0, "CustomerY");

  // Building relationship in the same way as in database
  var olx = OrderLine.CreateOrderLine(0, ox.Id, "ProductX");
  var oly = OrderLine.CreateOrderLine(0, oy.Id, "ProductY");

  context.Orders.AddObject(ox);
  context.Orders.AddObject(oy);
  context.OrderLines.AddObject(olx);
  context.OrderLines.AddObject(oly);
  context.SaveChanges(); // UpdateException: Unable determine principal end of Model.FK_OrderLine_Order relationship. Multiple added entities have the same primary key.
}

The mistake I did in my code is setting Id of both new orders to 0. Even if this is temporary Id it still has to be unique if you want to use it for foreign keys. You can probably ask at the moment why the context doesn't handle Id by itself? Simple because it can't. Context knows that Id is temporary and will be regenerated in store but context doesn't know details about store configuration. When you set up Identity in database you also set up seed and increment. Those two values are not known to the context so the context is not able to derive valid unique temporary Id which is not already used by the store. Suppose that context wrongly create some temporary Id and after that you load entity which already uses this Id = problem.

If i simply update my code to use unique temporary Id (I know how the store is configured) it will work. That is IMO one reason why I need to provide temporary Id to Create methods.

like image 61
Ladislav Mrnka Avatar answered Oct 17 '22 09:10

Ladislav Mrnka