In our database, every table has two DateTime columns, CreatedOn and ModifiedOn, set via triggers in SQL Server. CreatedOn is set on INSERT, and ModifiedOn is set on INSERT and UPDATE.
I am trying to use Entity Framework 4.1. How should I annotate/configure the two properties?
I think it involves the annotation [DatabaseGenerated(DatabaseGeneratedOption.Computed)], but should I use that annotation for both, or should I set [DatabaseGenerated(DatabaseGeneratedOption.Identity)] on the CreatedOn field?
According to MSDN Identity simply implies that The database generates a value when a row is inserted., which seems true here.
Also, should I use [Timestamp]?
Use Identity for CreatedOn and Computed for ModifiedOn. Identity means that value is set only during insert and returned back to application. Computed is set during each modification (including insert) and value is returned back to the application after each executed insert or update.
Just be aware that neither of these properties can be set in the application. Computed columns also can't be part of primary key or foreign key (it will not be your case).
This will only work with existing database. When using code-first Computed can be set only for timestamp or rowversion.
Timestamp is used for optimistic concurrency. If you mark a column as timestamp each update will contain condition WHERE timestampColum = #lastKnownValue. It will update the record only if last known value is the same as current value. If the value is different you will get an exception. It is usually used with timestamp SQL type. Using it with datatime would require some tests. Value of SQL datatime is not the same as value in .NET.
Related
I have an orderid integer column in a Postgres table called Orders and it's not the primary key. And there's a logic to automatically increment it considering the max value of the orderid and adding 1 to it.
One solution to this is creating a function in the database layer and set it as the default value to this column. But since that couples us to the database layer, we are thinking of something that's related to EF. We can't pass a SQL as the default value to orderid because postgres gives an error. We can also make it an auto-increment value but we don't wanna do that because the logic could change.
What we want is a way to run this subquery and automatically generate the value to orderid.
I presume what you want to achieve here is to maintain a separate non-primary key, auto-incremented unique id which is number. You can this by using a sequence.
1) Create the sequence via fluent API
2) Set the column to use the next value from the sequence
3) Make sure to create and run migrations before testing.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasSequence<int>("OrderNumbers")
.StartsAt(1000)
.IncrementsBy(1);
modelBuilder.Entity<Order>()
.Property(o => o.OrderNo)
.HasDefaultValueSql("nextval('\"OrderNumbers\"')");
}
Is it possible to get SaveChanges to produce an INSERT statement containing only columns that have assigned values for the associated properties.
For example:
administrator.Login = login
administrator.PasswordSalt = salt
administrator.Password = hashed
administrator.CreatedBy = "xxx"
db.Administrators.Add(administrator)
db.SaveChanges()
Should only have four fields in the INSERT statement. Right now, SaveChanges is adding all the fields, setting the unassigned properties to have a value of NULL, which prevents any default value being used. Example: CreatedDate has a default of getdate().
There are at least two different ways to exclude property from INSERT/UPDATE statement in compile-time:
1) EDMX: go to entity and set StoreGeneratedPattern option for a property to Computed or Identity.
If CodeFirst is used: try [DatabaseGenerated(DatabaseGeneratedOption.Computed)] attribite instead.
2) Add AFTER INSERT trigger to SQL table to update an inserted record with default values. How to update inserted field in trigger
I'm not sure it is possible to do in run-time in pure EF.
Is there a way to have entity framework use a SQL default value on an insert and yet allow updating to the field. We have an instance where a SQL table has an identity column "id" and another column which is set to ident_current("table"). The only way that I know of to get the field inserted with the default value is to set the field as DatabaseGenerated(DatabaseGeneratedOption.Computed) so that it is ignored on the insert. However by having that attribute then we cannot perform an update to the column. Also it's a self referencing foreign key so we can't do an insert then immediate update to get around the issue. Don't ask me why the table is designed this way - just the way it was set up before so we're kind of stuck with it for now. A simple diagram of our setup is below:
DomainClass:
Class1 {
public int id {get;set;}
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public int id2 {get;set;}
public string Name {get;set;}
}
SQL (pseudo):
Table (
id INT which is an identity(1,1) column,
id2 INT NOT NULL with a default value of ident_current("table")
Name nvarchar(50)
)
We would want the insert statement generated by EF to be:
INSERT INTO Table(Name) VALUES('Name')
and the update to be:
UPDATE table
SET id2 = *somenumber*, name = 'Name'
Thanks a lot for all the help. We are using EF 4.3.1.0 if that's needed as well.
There is no way AFAIK. See this and that.
The first link points to a suggestion about using sequences as primary keys, which seems like something you might want to do instead given your example code.
The second link points to a suggestion about generic handling of default values, which is currently not supported either, but would be another potential starting point toward adding support for what you need.
I am using EF 5 and SQL Server 2005, Model First (sort of).
By sort of, I mean that I typically build my schema in the SQL Server designer, but import the schema into EF so I have a visual view. There is often round-tripping.
However, I noticed that when I try to generate the DB schema based on the EF model, it skips all of the NEWID() default values that I have assigned as default values to my Guid IDs, but it doesn't skip the identity fields of type int.
I found this post explaining the reasoning for this:
Entity Framework 4 and Default Values
However, it doesn't answer my question: How do I get Entity Framework to generate a SQL DDL database schema with default values of NEWID() for my uniqueidentifier types?
NOTE:
I don't care about how to set them from the POCO entities and so forth (there are plenty of posts describing that) - my concern is getting the SQL DDL generated right so I can seed the database without worrying about these values going missing.
Using Entity Framework Migrations, you can use the GUID column builder and its DefaultValueSql parameter. The value of that parameter can be the string "NEWID()". This should take care of proper DDL generation.
Next you should declare these properties as database-generated using attributes or the fluent model builder, so that EF ignores the values set in your POCOs (which will be null for new objects).
I am sure I am not the first one to struggle with this.
I am using Entity Framework 1 (VS2008) and one of the columns in the table is ModifiedDate. It has DefaultValue in SQL Server (getdate()); so I would like to leave it the DB to do the generation. However, generated SQL has INSERT (... ModifiedDate) VALUES (... null), and the default value doesn't get inserted.
Is it possible to not specify this column at all?
By setting StoreGeneratedPattern in SSDL.