Ado.net & Entity Framework : creating entities - c#

I'm creating an entity diagram and I have a question about the StoreGeneratedPattern property on the Id's. I have both Identity and Computed options, and I'm not sure when to use each one. I guess that I should use Identity when it is generated by the entity and use Computed when is a foreign key, since is generated by another identity. Am I right or is the other way around ? Thanks!

If you would just simply look at the official MSDN documentation for this property, you would see:
Member name Description
-----------------------------------------------------------------------------
Computed A value is generated on both insert and update.
Identity A value is generated on insert and remains unchanged on update.
None A value indicating that it is not a server generated property.
So if you have a PK column that's an INT IDENTITY, then it's clear - use the Identity value.
The Computed value should be used for computed columns in your database tables, that are typically calculated on insert and re-calculated on update. This is NOT intended for foreign key columns! Those are just regular columns - do NOT set any StoreGeneratedPattern value for those!!

Related

DatabaseGeneratedOption: Identity vs. Computed

I am trying to understand the (functional) difference between the two DatabaseGeneratedOption's in Entity Framework (code first):
DatabaseGeneratedOption.Identity
DatebaseGeneratedOption.Computed
I have read the documentation, but I do not understand the functional difference between the two.
The option Identity is described as The database generates a value when a row is inserted. But I cannot update the value later if I try I get an exception saying that I cannot modify a column with Identity pattern.
The option Computed is described as The database generates a value when a row is inserted or updated. However, this is just what you tell Entity Framework, so far I have not been able to achieve this, without SQL triggers. If I try to update the value, nothing happens (Entity Framework refuses to overwrite the existing value).
So what I am left with, is two functionally identical options. I can have a default value in my SQL table, which will be applied on the insert. And I cannot update this value afterward (using Entity Framework). So where in lies the difference in how they should be used?
A computed column contains a value that is computed (hence the name) when the record is requested.
A computed column can be composed of other column values, constants and function return values.
You could for example create a computed column for an invoice expiry date:
CREATE TABLE Invoice
(
InvoiceDate DATETIME NOT NULL,
ExpiryDate AS DATEADD(DAY, 30, InvoiceDate)
)
Now if you mark this column as computed in Entity Framework, it will refuse any updates to that column, because it'll know the database won't support that.
So the documentation for that attribute is incorrect or incomplete.
A column marked as Identity will use the database-specific syntax to generate a primary key for the given table when inserting a record, being IDENTITY() in MSSQL and AUTO_INCREMENT for MySQL. A computed column will simply be marked as read-only, and you'll have to provide your own implementation (either in the database or in your migration file) to specify the computation (see How to add computed column using migrations in code first?).

EntityFramework Autonumeric value (not primary key)

My customer has requested that a field ("Code") in the database should be read-only incremental value starting from 100000. The funny thing is that the entity already has a primary key.
I don't know how to implement this easily with Entity Framework. What can I try?
Have you looked at the DatabaseGenerated Annotation?
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Code { get; set; )
This forces the database to generate the value and by using Identity it only generates the value on insert (not on update)
As far as I understand using this method would require you to set the value creation inside your database instance and EF would not generate it for you.
Sorry if this doesn't answer your question 100% but hopefully it sets you on the right track!
Only one identity column can be created per table. It is not possible to have more than one identity column.
One solution would be to use SQL Server Sequence which was introduced in SQL Server 2012.
CREATE SEQUENCE Code_Seq START WITH 100000;
SELECT NEXT VALUE FOR Code_Seq;

property 'StoreGeneratedPattern' set to 'Computed' are not supported. Use 'Identity' pattern

I am using Entity Framework database First approach
I have a table having composite primary key on
ID(int ,identity increment),
HashKey (binary) auto generated based on multiple columns using sql hashbytes.
Following is EF Column Mapping
ID storeGeneratedPattern="Identity" and
hashkey(binary) storeGeneratedPattern="Computed".
When i try to save using EF save changes method it is throwing below exception.
"Modifications to tables where a primary key column has property 'StoreGeneratedPattern' set to 'Computed' are not supported. Use 'Identity' pattern instead. Key column: 'HashKey'. Table"
I have applied composite primary key on these columns(Id,Hashkey) to make search faster as it contains cluster index. But not sure whether EF supports this.
I have seen below link. But i am not sure about the solution.
Property with StoreGeneratedPattern set to Identity is not updted after SaveChanges()
Can anybody help on this to resolve the issue.
'Computed' means EF expects SQL to generate the value after every insert/update. Therefore it doesn't make sense for it to be part of the PK.
You can just leave the identity as the PK and still create a clustered index with columns(id, hash).
Having said that, it also doesn't make sense to include a computed column in a clustered index. Every time the computed column is changed, the entire row needs to be moved to the new position.

How does Entity Framework handle Default constraints in the database table?

I am working on code which I cannot run until it's finished, as it is a long and tedious process to go through. I have been tasked to add a new table to the existing database, update the .edmx of the model and write a method to add new rows to the table through c# backend code.
In my situation, I have 2 default constraints on my table
SomeTable
------------
ID INT IDENTITY (1,1) PRIMARY KEY CLUSTERED,
SomeDate DATETIME2 NOT NULL DEFAULT GETDATE(),
SomeOtherField VARCHAR(1024) NOT NULL DEFAULT ''
Using the .edmx model of this table, I set SomeDate's StoreGeneratedPattern to Computed. I also manually double-checked it in the SSDL to ensure the computed StoreGeneratedPattern attribute was on the SomeDate Field in the SomeTable entity.
As far as I know, and are unsure of, when I have a the following code
public void AddSomeRow(...)
{
SomeDbContext context = new SomeDbContext;
var table = new SomeTable { SomeOtherField = "Value" };
context.SomeTables.Add(table);
context.SaveChanges();
}
I believe the SomeDate Field will be set to it's default constraint (because it hasn't been populated in the entity). Is this true?
Doing the same steps listed above for SomeOtherField, can I still manually give it a value (the value appearing into that field instead of the Default Constraint) or omit it (The default constraint will be set into that field)?
This question was hard to explain, I apologize if it doesn't make sense
The StoreGeneratedPattern implies that the value is always generated by the DB, so that you're not allowed to modify it. I.e it only makes sense for DB computed columns.
At least until EF 6.1 there is no direct way to support DB defaults. The only thing that you can do is move the default values out of the DB and generate them in the model (or code first) side. You'll find some work-aounds but they're not safe for some cases (specially for N-tier apps).

C# Entity Framework: Update Query Does not work

I have this simple code : (update value)
I'm trying to update column "c"
using (MaxEntities ctx = new MaxEntities())
{
aa orders = (from order in ctx.aa
select order).First();
orders.c = 22;
ctx.SaveChanges();
}
this is the table :
CREATE TABLE [dbo].[aa](
[a] [int] NULL,
[b] [int] NOT NULL,
[c] [int] NOT NULL
) ON [PRIMARY]
and values inside :
but i get an exception :
The property 'c' is part of the object's key information and cannot be modified.
I'm new to EF.
any help will be much appreciated.
The property 'c' is part of the object's key information and cannot be modified.
That's why you can't edit it. Maybe you need to add id column as a key with identity specified
As explained in another answer EF must uniquely identify every entity. If you don't have PK in the database, EF will infer some key. Key is considered as fixed so if EF inferred c as part of the key (and it did it because it uses all non-nullable non-binary columns) you cannot change its value. Moreover EF takes all tables without primary key as readonly so even if you remove c from the key in the designer and modify c value you will get another exception when you execute SaveChanges.
The reason for the second exception is in the way how EF describes model and the database. When EF inferred key, it did it only for description of your entities and for context's internal needs but not for description of the database. When EF tries to save changes it builds UPDATE statement from database description and without information about real database PK columns it will not be able to identify correct record for update (every update in EF can affect only single record - EF checks ROWCOUNT). This can be solved by cheating EF and updating its database description = by describing some column in the table description as primary key. This leads to multiple problems:
You must have some unique column in the database otherwise this method will not work.
You must edit EDMX manually (as XML) to add this change
You must not use default MS EDMX designer for updating your model from database because it will delete your change
Simple advice: Either use database tables with primary keys or don't use Entity framework.
Primary key missing here. Add primary key in table and it work.
I believe if there's no PK at all, EF uses all of the fields/columns as part of the key info.Here's a nice explanation: by #SteveWilkes of why. But what do your entities look like? The other possibility is that it doesn't have a property because the association is inside a different entity, if this is a foreign key.
EDIT
This got me thinking. There are just going to be situations where you have to work with legacy tables having no PK, even if you would never create such a thing. What about views? EF is a mapper - it has to uniquely identify that record so it infers and defines this key. Yes, you could use stored procedures, but could you also hack the XML and remove the keys from the table definition?
AND EDIT AGAIN
After posting this, I see #Ladislav Mrnka already said a similar idea (cheating EF and updating its database description), so it has been done (WARNING: Consume at your own risk - never tried). Quick google got me this blog with clear instructions:
Close the model designer in Visual Studio if it is still open and re-open the .edmx file in an XML editor
Find the edmx:StorageModels -> Schema -> Entity Container -> EntitySet element that refers to the table in question
On the EntitySet element, rename the store:Schema attribute to Schema
Remove the store:Name attribute altogether
Remove the opening and closing DefiningQuery tags and everything in between them
Save and close the .edmx file
But really, who doesn't like a PK? Can you not add an id?

Categories