Using Entity Framework CodeFirst, how do I create a created datetime column that gets populated with the current timestamp everytime a record is inserted for that table, and a modified datetime column that has a timestamp generated evertime a row is updated? Rails does this by default and I was hoping the EF generated database would have this as well, but it doesn't. Is this something that can be done with data annotations? If so, how?
Thanks!
It is not supported in EF. EF will not create these columns for you automatically. You must do it yourselves by either:
Have Created and Modified properties in every entity where you want to maintain these values. You must also manually maintain these columns in your application (common approach is overriding SaveChanges and set values accordingly).
If you don't need these values mapped (you never expect to use them in your application and you are happy with the logic in the database) you can create custom database initializer which would execute your custom SQL to alter tables and add those columns, default constraints for Created columns and update triggers for Modified columns.
Related
Using Entity Framework Core 2.0
Stuck with company's production database which has primary keys defined for each table but no foreign keys defined for any relationships.
Dependent records in the database have id fields which are intended to relate to the primary key fields of the parent record like you would normally find with a foreign key relationship/constraint. But these fields were all created as INT NOT NULL and are using a SQL default of '0'.
As a result dependent records have been inserted over time without requiring that a related parent record be specified.
Initially I defined my models in EF with integers and used a fluent configuration to specify "IsRequired". This was done so I could run migrations to create a test database for comparison against the production database to verify that my code first was correctly coded.
This then lead to the problem while using "Include" in my Linq queries which performs an inner join that results in dropping the records that contain the 0's in the id fields of the dependent record.
The only way that I have found to make this work is to model all of the id fields in the dependent entity as nullable integers and remove the "IsRequired" from the fluent configuration.
When using the "Include" it performs a left outer join keeping all of the dependent entities. This also means that any reference properties on the included entities are set to null instead of an empty string. This part can probably be fixed fairly easily.
The downside is if I wanted to use migrations to create a database now, all id fields in the dependent records would be created as NULL.
Is there anyone who has run up against this type of situation? Does anyone have any suggestions to try other than the approach I am using?
I haven't dealt with this scenario before but I wonder if you can solve it by defining the FK property as Nullable and then in the migrations, after the migration is created, edit it to add a HasDefaultValue property to ensure that it's 0? (doc for that migration method: https://learn.microsoft.com/en-us/ef/core/modeling/relational/default-values)
I created POCO classes and then EF created the database tables for me when I tried to access the data. This worked without problem. I have now populated my tables with data. Not just seed data but real data.
Now I would like to add another column to a table. I assume the first thing I need to do is to add a field to the POCO class but what's next after that? I now have my database filled with data. On the SQL side I know how to add the column myself but do I have to do something with EF or will it automatically pick up that my column was added to the table and my field to the POCO class?
You can use Code First Migrations (http://msdn.microsoft.com/en-us/library/hh770484(v=vs.103).aspx). It can update your database automatically or not.
I got one entity mapped to two tables. First of this tables has timestamp field.
What I want - if I modify field from first table it should check first table for concurrecny with timestamp column. The second table should'n updating. If I modify second table it should just update the second table. First table must be unchanged.
This is work if I set "Concurrecny=None" for the timestamp field in schema.
If I set "Concurrecny=Fixed" for the timestamp field and change properties from the second table it update the first table with current values.
How to make Concurrency check only for one of this two tables?
That is not possible. Once you map two tables to single entity they becomes one for entity framework and the time stamp is shared among them so if you do any changes to the second EF will always modify timestamp in the first. If you set Concurrency to None you are turning off the concurrency feature in EF and the main purpose of timestamp field.
I'm new to EF, and trying to work out the best way to do something
I have a procedure that returns the details of a table, but also a calculated value. What I'd like is for it to return this information to an entity that could contain this, whether it's the original entity, or an entity that's based on the original (so that if the original table changes, it will still map). What I'd like to avoid is maintaining 2 entities - 1 for the table, and 1 for the stored procedure results.
Thanks...
You could create a view that contained the table fields as well as the calculated values.
I do this to save new invoince in my Invoices database table:
// insert invoice into EDM
edmx.AddToInvoices(newinvoice);
// save EDM changes to datastore
edmx.SaveChanges();
I have a trigger on one of the columns that gets computed dynamically by the database. What is the 1) easiest way to get that value out of the database immediatelly after it changes, 2) What is the fastest way?
Thanks
You can either call Refresh:
MyEntities.Refresh(RefreshMode.StoreWins, someEntity);
...or configure the column in SSDL as store-generated if you never set it on the client.
Since the Entity Framework can't know anything about the trigger, you'd have to reload the entity with a new query.
I strongly recommend finding a different solution, if possible. Triggers can be evil.