DataAnnotation for creating Custom auto increment (or auto decrement) identity - c#

What I want to do is to create a primary key that has auto decrement:
Id BIGINT PRIMARY KEY IDENTITY(-1,-1)
I searched for it and I could only find the following DataAnnotation for setting the Identity:
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
But this not fullfill my need of setting start and increment values. And if I want to increment by 1, and starting from 1 actually the following that I always use works for me:
[Key]
public long Id { get; set; }

Hi You can achieve this output by using the database initialization or migration
There is no direct way to implement this in Code First. So, for using any of these options, you need to
customize the DB initialization: This is done by implementing your own database initializer class and execute the desired SQL commands from the Seed methods (look for the implementation of public class MyInitializer in the linked article)
or to customize a migration: you can execute any SQL Command in the Up() or Down() method of your migration
Source: https://stackoverflow.com/a/23964887/3397630
Kindly look at the above url , the asker commented that ,By using above technique could be able to solve the problem. so hope it will be useful for you too.
Thanks
Karthik

Related

EntityFramework code first: Set order of fields

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

Generate Guid on database but only when not set in entity

I have a case where I need to add a Guid Property that is NOT the primary key, and that could be shared with several objects in the table.
What I'd like to do is:
Generate the Guid on the database when I don't give it a value
Set a Guid (instead of generating it) when I have its value
Both of this would be done on Insert only, Updates won't touch these values.
What I have tried:
Add the [DatabaseGenerated(DatabaseGeneratedOption.Identity)] attribute: only works when I don't need to set the Guid manually
Add the [DatabaseGenerated(DatabaseGeneratedOption.Computed)] attribute: doesn't work when I don't set the Guid manually
I've seen quite a lot about this topic, and the closest thing would be this article:
http://www.davepaquette.com/archive/2012/09/23/calculated-columns-in-entity-framework-code-first-migrations.aspx
But we don't (and won't) use Migration in our project, so that doesn't seem fit.
or this SO question, but that would mean generating Guids in .Net (which doesn't seem to be very clean, at least in my opinion): EF, Code First - How to set a custom Guid identity value on insert
Is there a way to generate the Guid Database side, AND set it when I need to in EF Code first?
If not, what would be a good alternative? Is it really a bad idea to generate Guids on the .Net side? (I could go with that if nothing else is possible)
I will assume that you are using MS-SQL , then you can do the following
To use the execute command
public class YourDbContext: DbContext
{
public YourDbContext():base("ConnectionString")
{
if (Database.Exists())
{
Database.ExecuteSqlCommand("if object_id('CT_DefaultGuid') is null alter table YourTable add constraint CT_DefaultGuid default newid() for YourColumn");
}
}
}
To set the Id from .Net, you can do the following
Create a Base Entity contains Id property
In the constructor you check if the Id is empty then initialize it
Let all the entities you have to inherits from this class
Your base class should look like
public class BaseEntity
{
public BaseEntity()
{
if(Id==Guid.Empty)
Id = Guid.NewGuid();
}
public Guid Id{get;set;}
}
To use the migration for existing database
from PMC => Enable-migrations
from PMC => Add-Migration "FirstRun"
open the generated migration file and make sure to empty the Up and Down methods ( this will not apply any changes on the database)
Add the corresponding alter column fluent code using Sql("") method in the Up method
from PMC => Update-Database -Script , to make sure that only sql statement generated is the alter table statement
from PMC => once you are sure that the desired statement is the only appearing in the SQL script , then apply : Update-Database.
Your class should like this
public class FirstRun : DbMigration
{ public override void Up()
{
Sql("alter table YourTable add constraint CT_DefaultGuid default newid() for YourColumn");
}
}
I recommend the last approach, it will be executed once, and you can add changes later to your database.
Hope this will help you

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.

MVC setting up model id value

I'm new to MVC so please bear with me.
As a learning project I've decided to make a Fantasy Football website. The NFL has a really cool api that lets you download TONS of stats and other info. As part of the data stream, each player has an id number (actually they have like 3 ids but I'll just use the main one).
Here is the problem: I want to set up my models to use the playerId value (passed in from an AJAX call on the NFL api) as a PK on my Player class and FK on several other classes/tables. However, you normally can't assign the PK Identity value on a db. I did a lot of searching for a workaround and tried several tricks but none worked. I tried playing with the db manually and ended up ruining the project and having to start over. I've thought of making the playerId a surrogate key but that seems needlessly complicated. Theoretically I would periodically call the api for updates and those are all tied to that playerId value so making that playerId the PK is what makes the most sense.
Is there a way to do this?
Turn off autoincrementing on your primary key column in your database. If your using SQL Server then don't set identity column. Set up your model like so:
public class Table_1
{
[Key]
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None)]
public int playerId {get; set;}
public string player_name { get; set; }
}
Then set playerId when you create the record.
You are going to have to turn off the Identity specification on the SQL Server side:
I finally got this to work.
First, add the annotation to the PK (playerId in my case.
[DatabaseGenerated(DatabaseGeneratedOption.None)]
Second, when you do a migration you have to proof read it. I ran into quite a few errors because the migration code was just plain wrong. In one case I changed the name of a PK column and the code tried to add the new PK column before dropping the old one. All I had to do to correct this was to rearrange the steps. Make sure to strip off the "identity: true" from the column which is to be the PK.
*Note: My issues with the migration tool may be in part due to my using a version of VS2012 which I haven't updated in a while. Some of the kinks may have been worked out since then.

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