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;
Related
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?).
My problem is the following : I map my view to an object through Entity Fluent API. I needed a view containing an few left joins, an there were no unique identifier in the tables, therefore Entity always returned the same set of object. In a few different threads / blogs, I saw a solution consisting of add a column with
ROW_NUMBER() OVER (ORDER BY Id))
I then tried to map it in Entity :
in my class I add a property
public long Row { get; set; }
and in my configuration class I add
HasKey(imc => imc.Row).HasColumnName("Row")
Apparently, the mapping works. What doesn't work is that, when I query the objects with linq, even a Count() will timeout ; however the request itself only returns about 200 lines when used in a SQL Management Studio environement.
Has anyone ever seen this issue ?
EDIT:
I have been able to bypass the problem by replacing the "row_number()" with a newid() in the MS SQL View, but I'm still afraid it might be a problem later on.
Your query is slow which causes the timeout. About 1 million people have seen this before. You would need to analyze the query plan. Computing a row number over the whole table if unindexed can be slow. Also, a row number cannot be used as a key because it's values changes when you change the underlying data. EF does not support changing keys.
If you use newid() as the "key" in the view then you get fresh IDs each time. I think you might not be aware of the fact that a view is merely a shortcut for that particular query. It's contents are not stored anywhere.
Introduce a column that can be used as a key. For example an IDENTITY column.
I am using an Entity Framework 4 connection to connect to a SQL 2008 server to do database handling for my application.
I am using C# in Visual Studio 2010 and my question is regarding Primary Key fields that are incremented by the SQL itself, is it possible at all for me to be able to find the ID that will be used next by the database.
The reason why I cannot just find the last item and +1 is because if my table contains items 1,2,3,4 and 5, removing item 5 then adding another will make the next item become item 6, rather than 5 again (As I use the Identity Specification in SQL, but this must be used).
I cannot find any method such as Item.ID.GetNextIdentity() or something like that and have looked through as many similar questions like this but to no avail.
Any help would be appreciated
There is no reliable way to use auto incremented ID and show it in a form before you do the save. That is wrong architecture. If you want to have ID shown before saving the form you must either:
Not use auto incremented column as ID and handle uniqueness yourselves
Save the form immediately when user starts creating it in some initial empty state and the final form confirmation will do only update
Why you cannot ask for next ID? Because if you do it in any way nobody says that received ID will be really used for your form. If another process / thread / application inserts form between your ID retrieval and your form persistence, the Id you shown will be assigned to that inserted form.
Also if you are using auto incremented primary keys in the database you cannot assign the key value in your application - the value will not be used and database can override it with its own.
Quite agree with Ladislav Mrnka, though, this kind of functionality could be needed.
One bypass suggestion would be :
// Insert existing object in data base via EF, but PK is missing ...
using (var Es = new MyEntities())
{
try
{
// Allows you to get next pk
var e = new Model.TableXXX();
// Set pk to existing entity which has no pk
existingEntity.PkField = e.PkField;
// Save existing object and let garbage collector take care
// of newly created entity
Es.TableXXX.AddObject(existingEntity);
Es.SaveChanges();
}
catch (Exception ex)
{
// implement exception
}
}
DBCC CHECKIDENT ( table_name, NORESEED )
Returns the current identity value and the current maximum value of the identity column.
Entity Framework 4 Returning KEY/Primary Key
I’m Trying to find a way to Return a Key/Primary Key without having to create a stored procedure to do it for me using:
CREATE PROCEDURE [dbo].[UserRecords]
(
#Name varchar(10)
) AS
-- INSERT the new record
INSERT INTO MyTable (Name)
VALUES(#Name)
-- Now return the InventoryID of the newly inserted record
SELECT SCOPE_IDENTITY() AS ID
Though Visual Studio 2010 I then Use the Add Function Import From the Model Browser and Create a Complex Type.
Then Though C# i use the Following Code to check its working.
SQL_DB_Entities DB= new SQL_DB_Entities();
var ReturnValue = DB.UserRecords("BOB").First();
Console.Write(ReturnValue.ID);
Console.Read();
I'm simply looking for a better way to return the ID and also being very sure im not going to cause head aches for myself laster on down the track.
If you feel this is not the best way to return the key please let me know.
I have Tried it this way but returns 0
SQL_DB_Entities DB = new SQL_DB_Entities();
User UserObject = new User{Name = “BOB”};
DB.AddToUserTable(UserObject);
DB.SaveChanges():
Int key = UserObject.ID;
Console.WriteLine(key.ToString());
I should also mention that the DB is looking after the Primary Keys not my application.
If you correctly setup StoreGeneratedPattern to Identity in your entity and if you have autogenerated PKs in the database, EF will fill the Ids of your inserted entities after each save changes. Check this article to understand store generated pattern.
Normally PKs are dealt with as a particular property on an EF Object EntityKey. You are probably best to have a look at EntityKeys.
The usual way is to set the StoreGeneratedPattern property of the PK column in your model as Identity. Or if you are using code-first, annotate the property with:
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
I am not sure whether this works with sprocs, though. By the way, any special reason you are using sprocs in this case?
Rightly or wrongly, I am using unique identifier as a Primary Key for tables in my sqlserver database. I have generated a model using linq to sql (c#), however where in the case of an identity column linq to sql generates a unique key on inserting a new record for guid /uniqueidentifier the default value of 00000000-0000-0000-0000-000000000000.
I know that I can set the guid in my code: in the linq to sql model or elsewhere, or there is the default value in creating the sql server table (though this is overridden by the value generated in the code). But where is best to put generate this key, noting that my tables are always going to change as my solution develops and therefore I shall regenerate my Linq to Sql model when it does.
Does the same solution apply for a column to hold current datetime (of the insert), which would be updated with each update?
As you noted in you own post you can use the extensibility methods. Adding to your post you can look at the partial methods created in the datacontext for inserting and updating of each table. Example with a table called "test" and a "changeDate"-column:
partial void InsertTest(Test instance)
{
instance.idCol = System.Guid.NewGuid();
this.ExecuteDynamicInsert(instance);
}
partial void UpdateTest(Test instance)
{
instance.changeDate = DateTime.Now;
this.ExecuteDynamicUpdate(instance);
}
Thanks, I've tried this out and it seems to work OK.
I have another approach, which I think I shall use for guids: sqlserver default value to newid(), then in linqtosql set auto generated value property to true. This has to be done on each generation of the model, but this is fairly simple.
There's two things you can do:
either just generate the GUID in your C# client side code and use that value
create a DEFAULT constraint on the GUID column in SQL Server that defaults to newid() for the column - the SQL Server will make SURE to always add a default - unless you specify a value yourself
As for the self-updating date/time columns - here you probably have to use either client-side logic to do that, or if you want to do it on SQL Server, you'll have to write a trigger. That's really the only way to update a specific column everytime the row gets updated - there's no "autoupdate" constraint or anything like this (and the default constraint only work on INSERTs, not updates).
Something like this might work:
CREATE TRIGGER TRG_UpdateDateTimestamp
ON (your table name)
AFTER UPDATE
AS
IF NOT UPDATE(DateTimeStamp)
BEGIN
UPDATE (yourtablename)
SET DateTimeStamp = GETDATE()
WHERE EXISTS (SELECT * FROM inserted AS i
WHERE i.OID = (yourtable).OID)
END
Marc