I want to create a DateTime field so that it will have a default GETDATE() once it gets to the database. So I did this:
public class Specialty
{
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime? CreatedDate { get; set; }
// other properties not shown for brevity.
}
So I ran Add-Migration in the PM> console. It resulted in this (not all lines are shown) in the Up function:
AddColumn("dbo.Specialty", "CreatedDate", c => c.DateTime());
I understand that nullable of c.DateTime(...) is true by default, so I understand why it's not specified. BUT where is defaultValueSql: "GETDATE()"?
I know I can put it in manually, but that seems to defeat the purpose of Add-Migration and makes [DatabaseGenerated(DatabaseGeneratedOption.Computed)] useless. I know for a fact that defaultValueSql's default is not "GETDATE()" because it doesn't show up when I look at column properties in SQL Management Studio.
What's missing? Does the name "CreatedDate" violate an EF convention, then? Is there another library that I should have referenced besides System.ComponentModel.DataAnnotations.Schema?
[DatabaseGenerated(DatabaseGeneratedOption.Computed)] is not useless, it tells the Entity Framework that the column is required in the database but is computed by the database. So it knows that it should create the column in a migration and it knows that it should not try to update its value nor insert a value.
What is missing is that you have to add the computation to the database column. And you do that by modifying the migration:
AddColumn("dbo.Specialty",
"CreatedDate",
c => c.DateTime(defaultValueSql: "GETDATE()"));
There is currently no way to specify the sql in a data annotation, and I suspect that there never will be because the sql could be database specific, and is therefore best kept within a migration rather than being allowed to leak into the model definition
I ended up inheriting all entities from a base class, following these instructions.
This means making a custom migration class for the CreatedDate and UpdatedDate column, and it works perfectly with minimal effort.
Related
I want to do some changes in a table that is already exist(i am using sqlite). I want to remove a Attribute of a property in a class. Remove [Required] attribute. How can i do that, what should i change, should i some changes in DbContext or migration folder or what commands can i use in package manager console.
public class Appointment
{
[Required]
[MaxLength(50)]
public string Company { get; set; }
This is a good example of why it is better to use fluent API then attributes to specify your database: you want the same class to be used in a different database.
The DbContext defines the database: what tables are in it, how do the tables relate towards each other, what classes do represent the tables, and what are the constraints to the tables.
For instance, maybe in one database you want Company to have a MaxLength of 50 characters, in another database you might desire a length of 100 characters. Some databases need a simple DateTime, others require a DateTime2. Or maybe you want a different precision for your decimals?
Hence it is usually better to specify the database statistics where it belongs: in the definition of the database, which is the DbContext.
Back to your question
It depends a bit on the entity framework that you are using on how the database reacts if during migration you use remove the Required attribute and move it to fluent API. I guess it is best to experiment with it.
In OnModelCreating, or the migration equivalent of it, you will have something like:
var entityAppointment = modelBuilder.Entity<Appointment>();
var propertyCompany = entityAppointment.Property(appointment => appointment.Company);
propertyCompany.IsOptional()
.HasMaxLength(50)
...; // other non-default specifications of Company
// like columnName, IsUnicode, etc
When migrating the statements might be little different, but I guess you get the gist.
I am wondering if it makes sense to create a migration for a scenario where there aren't necessarily model changes, but the enum property on a model has been changed. I'm using .NET 4.6.2 and Code-First Entity Framework
I have the following EF-tracked log model:
[Table("Logs")]
public class Log
{
public int Id { get; set; }
public DateTime Timestamp { get; set; }
public LogType Type { get; set; }
}
The LogType enum currently has around 40 values, of which, 13 have become obsolete or deprecated. I am going through the process of removing references to the obsolete/deprecated enum values.
As such, the values of the LogType enum are being changed. For example, LogType.ConnectionTimeout used to have the value 16, but now has the value 3.
In my database (MSSQL), the Type column is stored as an int, and I have written SQL that deletes all entries with an obsolete/deprecated enum value, and I have also written SQL that updates the other enum values to match what their new values are (e.g. changing 16 to 3 using my previous example of Type.ConnectionTimeout).
My question is this: Is it a good practice to put that SQL in a migration that is able to be Up()'d and Down()'d? My other question is, is that even possible? Or does there need to be actual model changes to create a migration? I'd like to be able to have this SQL tracked and stored in version control, as well as the ability to Up() and Down() it in the future if need be.
Thanks, and apologies in advance if this is a duplicate -- I wasn't able to find a similar question through my searches.
I am using EntityFramework with the "Code first" approach with migrations.
I have successfully generated tables from my models, but the columns are being added in an alphabetical order rather than the order inside my model.
I have tried this:
[Key, Column(Order=0)]
public int MyFirstKeyProperty { get; set; }
[Column(Order=1)]
public int MySecondKeyProperty { get; set; }
But that doesn't seem to be working.
How can I manually set the order of the fields in the database?
I am using ASP.NET Core and EF Core (SqlServer) v1.1.0.
Currently ordering columns by class property is not implemented.
Here's the long discussion about column ordering. Column ordering #2272
Update as of 07/12/2017
This issue is in the Backlog milestone. This means that it is not
going to happen for the 2.0 release. We will re-assess the backlog
following the 2.0 release and consider this item at that time.
Update as of 06/10/2019
Issue 2272 shipped with EF Core v2.1 and matches the order of the columns in the generated table to the order of the properties in the class. However, as #lloyd-conrade mentioned, this is only useful for initial creation
A new issue, #10059, has been created to track the possible implementation of respecting the Column attribute's Order property.
If the implementation of #2272 is insufficient for you and specifying something
like [Column(Order = 1)] would help, please vote for this issue and add details
about your scenario (if not already listed) below.
Note the "Punted for 3.0" label was added on May 10th, 2019, which is to say it will not ship in EF Core 3.0.
Update: In EF Core 2.1, for the initial migration at least, columns are added to tables in the order in which the relevant properties are declared in their respective classes, rather than in alphabetical order. See here. But note that any subsequent Entity Framework migrations performed on the same tables won't change the column order of the columns created earlier.
At this moment EF core doesn't support it.But there is a workaround for that.That is, you can explicitly specify SQL on your migration operation.
Instead of using the CreateTable method in your migrations, you need to explicitly write the SQL as shown below.There you can give the order as you wish.
migrationBuilder.Sql("CREATE TABLE Properties(
MyFirstKeyProperty INT NOT NULL,
MySecondKeyProperty int NOT NULL,
AGE INT NOT NULL,
......
......
PRIMARY KEY (MyFirstKeyProperty)
)");
You can read about the rowanmiller's commnet here about how to sort out that issue just for now
You can use this solution to add support for explicit column ordering to your project: https://github.com/premchandrasingh/EFCoreColumnOrder. This solution adds the HasColumnOrder extension method. There is an example of use in the Sample folder. Do not forget to replace the corresponding services in your DbContext.
the order of the columns you mention is used to specify the order of the columns a compound foreign key, as it is in the case of some tables that have two or more fields as foreign key that refer to other tables, in that case you can use Column (Order = n)
As of Entity Framework Core 6 you can specify the column order with an annotation:
[Column(Order = 1)]
public int Id { get; set; }
https://learn.microsoft.com/en-us/ef/core/modeling/entity-properties?tabs=data-annotations%2Cwithout-nrt#column-order
Using Entity Framework and ASP.Net, one of my entity models is:
public class Records {
public bool IsPublic {get; set;}
// Some other properties
}
I have changed the model to:
public class Records {
[obsolete]
public bool IsPublic {get; set;}
public RecordAccess AccessLevel {get; set;}
}
Where
public enum RecordAccess {Public, Private, Group };
After this migration, I need to initialize the new column (AccessLevel) based on IsPublic column and some other tables.
So I wrote the c# code to initialize the AccessLevel and put it in the Seed method.
Note
I want to delete IsPublic column since it's no longer being used.
I have 4 different databases which I'm working on: localdb, test server, staging server and production server. These databases might not be in the same state. So data and the table schemas might be different.
Question
Is Seed method the right place to put the initialization?
(If I delete the IsPublic from the Record class the code won't be compiled)
How can I roll back the migration and data to what it was before?
I would write the initialization in the migration itself using the Sql("[INSERT SQL HERE]") method. This is assuming that this is a one time move.
If you put it in the Seed method, the code will run every time the database is updated with new migrations, which means that you will probably end up writing code that checks to see if this has already been done and ignoring it, making it one time use, which basically makes it a migration.
To rollback your database, in the Package Manager Console window, use the Update-Database -TargetMigration [name of last good migration]. More Info here.
In my SQL Server database schema I have a data table with a date field that contains a default value of
CONVERT(VARCHAR(10), GETDATE(), 111)
which is ideal for automatically inserting the date into the new record when manually entering records in to the database.
The problem I have is that when using the Entity Framework and mapping the Date field, that the Entity Framework inserts a default value of DateTime.Min when the entity is instantiated.
I cannot map the Date field to a nullable DateTime, i.e. DateTime?, nor am I able to use either CONVERT or DateTime.Now.Today in the default value of the Entity Designer as it only accepts hard-coded constant values.
I can of course explicitly set the DateTime field in C# whenever the object is created, either explicitly in code, in the constructor of a partial class, or even during the saving changes event.
Are there any other ways of achieving what I want where the default value calculation stored in the database table is actually used instead?
Create a partial class for your EntityObject, add a default constructor, and set default values in it.
public partial class YourDBObject
{
public YourDBObject()
{
this._DateField = DateTime.Now;
}
}
You can use a database trigger, which, on insertion, checks if the inserted value is DateTime.MinValue (01.01.0001) and replaces it with the calculated value you desire. This MSDN article describes how to create a trigger.
A little "flaw": with this solution you would have to store the new object to the database and read it back afterwards to update your object with the calculated value.
This is really unfortunate. The answers referencing StoreGeneratedPattern are not a true solution, that doesn't allow you to ever set the value.
All the team would have to do is something like this:
[Required]
[DefaultValue] // suggested attribute, whatever you want to call it
public DateTime Created { get; set; }
If a field is marked DefaultValue, then at EF's SQL generation time, properties with this attribute get checked if field == default(DateTime), if so, then simply omit that column from the generated code.
Just happened to cross through this issue. Entity Framework do not support default values on its own. You need to set the property StoreGeneratedPattern = Computed on the column in the Edmx file entity. The default value what you set in the Database will then precedence on what EF sets by default i.e. DateTime.Min
I just ran into this - I worked around it by setting the date (the field I needed auto generated) in the constructor of the Entity using a partial method. Whether this is Ideal or whether it works in all cases is yet to be seen, but it has fixed my problem so far.
I had a similar problem using RIA Services with the Entity Framework. I was not able to set the value in the default constructor on the client side because the entity classes that are generated there already have an empty default constructor.
The solution that I used was to implement the OnCreated partial method for the entity on the client by setting the required default value.
I think the answer provided by lazyberezovsky on another SO question is the straight forward solution to this problem Entity Framework and Default Date
The date field can be mapped to DateTime? only if the column is nullable in the database.