EntityFramework code first: Set order of fields - c#

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

Related

How to Remove a Attribute of a Property in a Class

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.

How to insert an entity with autoincremented field in .net core without messing with SQL Server 'Identity_insert on'?

What would be the best practice for storing some entity in a SQL Server database, when I have an Id property which is autoincremented (identity)?
This is for a .NET Core application, using Entity Framework Core. I suppose that I could just create some new entity without the identity id, and move the values of my old entity to my new entity the store it in the .Add method of my current context, or execute a command for enable the 'SET IDENTITY_INSERT ON', but both of those approaches looks messy, I'm guessing that there is a cleaner way to achieve this.
//user has autoincremented property
public IEnumerable<User> SaveUser(User user)
{
context.add(user);
context.SaveChanges(); // Exception Cannot insert explicit value for identity column in table
}
I expect to get to do it in a way that I could reuse it in the whole application, because if my entities keep increasing in size, I would have to write this messy code all around.
To start with, I would like to ask/point at your model class. Not sure how you are having your EF on .net core, but if you are to have a model (be it code first or model first),
lets just say, your Entity model looks similar to below:
User
{
UserId (as int),
UserName (as string),
BirthDate (as date)
}
You can achieve the identity insert by below approach:
public class User
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserId {get;set;}
public string UserName {get;set;}
public DateTime BirthDate {get;set;}
}
Please explore and learn about Code first approach, Modelling your data, repository patterns (may be the ideal in my perspective but depends on case or could be a good learning) and see to the attributes, annotations decorations for EF models.
To explain on what actually drives the auto identity by the above annotations,
Identity generation (auto identity prop)
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
is the driving factor, also depends on the data type. some data types may need additional param configurations. Explore when you try out on your solution. For example, you can use Guid data type and see how it turns out in your Db.
primary key or key attr
[Key]
is as simple to denote as the primary key field in the model/entity structure. This may not be helping or running the auto identity but, i am explaining about this on why i added this attribute in my sample code above.

Entity Framework's "Index" decoration is not creating an Index

Here is the super simple class I'm trying to create.
public class Company
{
public int ID { get; set; }
[Column(TypeName = "VARCHAR(254)")]
[Index]
public string Name { get; set; }
[Index]
public int stupidField { get; set; }
}
My goal was to force Name to be unique, so I added the decoration [Index(IsUnique = true)]. But no unique index was created, so I figured I'll first try to solve the simpler problem of creating any index. Because I read here that indices cannot be created for columns of type varchar(max), I limited the length of the Name field. Still no luck. I even tried a few different syntaxes for limiting the length of the field, but still no index.
To see if something other than string length was at play, I created the integer field stupidField, but I can't index that field either. So now I'm completely out of ideas as to what could be wrong. Please help me!
Check out this screenshot from MS SQL Server Management Studio that shows that my fields are being created but not the indices.
Note: I'm certain migrations are not the issue.
Some of the people I've read about on SO were updating their classes, but those changes were not reflected in the database because of problems with their migrations. That is not relevant here. I delete the database and recreate it every time I make a change. (I even make silly changes like renaming my fields, just to make sure that I can still affect the database.)
Turns out I'm actually using Entity Framework Core, not Entity Framework. In Entity Framework Core, indices cannot be created using attributes, although they can be created using fluent API. See Microsoft's documentation.

Code first, using a non-sequential Id

I have a code first project with a few tables, I am trying to determine that for a certain object the Id with which it will be inserted will not be the sequential Id that sql provides but an Id i will provide.
Although the code in my repository is creating the object properly and assigns it the wanted Id once it is inserted to my DB in the:
DbContext.Set<Containers>().Add(entity);
It is inserted as the next sequential Id.
In my code first the Id column for the base Entity from which all my entities derive is:
public int Id { get; set; }
I am looking the change to the Id's only in this entity.
Any suggestions?
this is the default behavior: when you don't alter it explicitly, EF will create an autoincrement column on the ID, if it's type is fitting.
To alter it, use Fluent API:
modelBuilder.Entity<Containers>().Property(x=>x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
or Data annotations:
[DatabaseGenerated(DatabaseGeneratedOption.None)]
Maybe you'll have to run an migration after this to alter the table to non-autoincrement also. If you don't want to do that, you'll have to use Identity insert, wrapped in a transaction, every time you want this behavior.

Duplicate 'System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedAttribute' attribute

I am using EntityFramework version 4.4, code first and I have created my data model in a separate project (MyApp.DataModel).
Because I am building a Silverlight application, I am using a WCF RIA services. The code required by the ria services is in a different project (MyApp.Services). This project has a reference to MyApp.DataModel.
An example of an data model:
[Column("Remaining")]
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public virtual decimal? Remaining
{
//
}
When I build MyApp.Services I get an error
Duplicate 'System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedAttribute' attribute
Indeed, in the generated code there are two attributes
[System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedAttribute(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Computed)]
[System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedAttribute(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Computed)]
If I remove DatabaseGenerated, then on insert I get an error
The column "Remaining" cannot be modified because it is either a computed column or is the result of a UNION operator.
Any idea why and how to solve this problem?
As far as I understand the documentation here: http://msdn.microsoft.com/en-us/data/gg193958.aspx , Key already defaults to DatabaseGeneratedOption.Identity, so you wouldn't need to add the DatabaseGenerated separately.
Excerpt from the part under DatabaseGenerated:
a key property will become an identity key in the database. That would
be the same as setting DatabaseGenerated to
DatabaseGenerationOption.Identity. If you do not want it to be an
identity key, you can set the value to DatabaseGenerationOption.None.
To be honest, I haven't tested this, but can you confirm that after removing [DatabaseGenerated(DatabaseGeneratedOption.Identity)] , the other attribute still remains in the generated code?
If you mark the property as DatabaseGeneratedOption.Identity the EF understand that this is the key attribute.
Actually if you don't place none attribute (Key or DatabaseGeneratedOption.Identity) the EF will assume that this is the id as the property ends with 'ID' and will create a autoincrement field at database.
The DataAnnotations are optional in many cases (like yours).
You also don't need to mark this property as virtual as it's a primitive type. Use virtual just to associate others classes (lazy load).

Categories