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.
Related
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.
Please see the class below:
public class UndergraduateEntityTypeConfiguration : IEntityTypeConfiguration<Undergraduate>
{
public void Configure(EntityTypeBuilder<Barclaycard> undergraduateConfiguration)
{
undergraduateConfiguration.HasData(
new Undergraduate(1, "Undergraduate")
);
}
}
and the code below:
public class StudentEntityTypeConfiguration : IEntityTypeConfiguration<Student>
{
public void Configure(EntityTypeBuilder<CreditCard> studentConfiguration)
{
studentonfiguration.ToTable("Student", StudentContext.DEFAULT_SCHEMA);
studentConfiguration.HasKey(o => o.Id);
studentConfiguration.Property(o => o.Id)
.ForSqlServerUseSequenceHiLo("studentseq", StudentContext.DEFAULT_SCHEMA);
studentConfiguration.HasDiscriminator<string>("Type")
.HasValue<Graduate>("Graduate")
.HasValue<Vanquis>("Undergraduate");
}
}
Notice the Student ID field (in the Student table) uses a HiLo sequence. However, in UndergraduateEntityTypeConfiguration I have to explicitly pass an ID number to the Undergraduate constructor to add the Undergraduate record to the Student table.
The code works as expected. However, I am confused why I have to pass an ID (1) myself. Is there a way of creating the Undergraduate record like this:
undergraduateConfiguration.HasData(
new Undergraduate("Undergraduate")
);
Note that this time no ID is passed to the constructor. If I do this, then I see an error, which says: "The seed entity for entity type 'Undergraduate' cannot be added because there was no value provided for the required property 'Id'".
No. This is a specific requirement for EF Core data seeding with HasData (a.k.a Model seed data) coming from the design of the feature.
It's not specific for HiLo sequence generated columns, but all auto generated columns (including the most used auto increment (identity) and database sequence generated columns). The explanation in the documentation is as follows (pay special attention to the first bullet):
This type of seed data is managed by migrations and the script to update the data that's already in the database needs to be generated without connecting to the database. This imposes some restrictions:
The primary key value needs to be specified even if it's usually generated by the database. It will be used to detect data changes between migrations.
Previously seeded data will be removed if the primary key is changed in any way.
If it's a problem for you, consider switching to the more traditional way of data seeding.
I'm new to Entity Framework in C#.
I'm having one computational column in my table table1(example). I will calculate the computational column value based on the other columns value. I don't want Entity Framework to include the computational column while performing insert/update operations. How can I make the EF to avoid that particular column. But I want to set the value for that particular column manually.
I searched for the same but i couldn't able to get the answer for my question. Kindly help me and thanks in advance.
You can use the NotMapped Annotation
Code first convention dictates that every property that is of a
supported data type is represented in the database. That property can
be created dynamically and does not need to be stored. You can mark
any properties that do not map to the database with the NotMapped
annotation.
[NotMapped]
public string Something
{
get
{
return _something;
}
set
{
_something = value
}
}
Update : this is will not map to the dB, so is probably not what you are looking for
Just to make this a more complete the DatabaseGenerated Annotation, are the droids you are looking for
An important database features is the ability to have computed
properties. If you're mapping your Code First classes to tables that
contain computed columns, you don't want Entity Framework to try to
update those columns. But you do want EF to return those values from
the database after you've inserted or updated data. You can use the
DatabaseGenerated annotation to flag those properties in your class
along with the Computed enum. Other enums are None and Identity.
Which can be used with the DatabaseGeneratedOption
Computed : The database generates a value when a row is inserted or updated.
Identity : The database generates a value when a row is inserted.
None : The database does not generate values.
[DatabaseGenerated(DatabaseGenerationOption.Computed)]
public string Something { get; set; }
As you calculate your column server side the correct way is to configure the field at the context level with:
HasComputedColumnSql for ef-core
DatabaseGeneratedAttibute for EF-6 (HasDatabaseGeneratedOption for the fluent api)
If you use NotMapped, you will not get the value from the database.
For school I'm working on a project in C# WPF and SQL Server. I made the database and use Linq to SQL. Now I got the following tables:
Patients
-------
ID int PK
name varchar
insurancecompany int FK
Insurancecompanies
-------
ID int PK
name varchar
insurancecompany in patients is a FK to id in insurancecompanies
I left out a lot of unnecessary columns for my question since it would take too long. So I added the database tables to my Linq to SQL database model. I created an instance to the patient class. Looking at it, I see 2 properties. One is insurancecompany, which is an int. The other is insurancecompany1, which is an insurancecompany type.
Is it safe to make the int private, or remove it? Or is there a way to make it so there's only one property?
What is happening is that database model sees that you have a foreign key relationship to Insurancecompanies, it looks at the value you've assigned it and then finds that insurancecompany and adds it as an additional property which it calls "insurancecompany1" (it would have called it "insurancecompany" but couldn't because you already have a property with that name).
This is a nice feature because it makes it easy to look at the insurance company for a given patient without needing to use joins;
var dave = patient();
//assign a patient from your database to "dave" here..
var nameOfDavesInsuranceCompany = dave.insurancecompany1.name;
If you remove the int insurancecompany you will loose this feature because the model would no longer be able to work out which insurance company to look at. You could make it private but you would loose the ability to assign an insurance company to patient by simply giving an int value (you would always have to set an insurancecompany object to insurancecompany1).
If you don't like the names, you could rename insurancecompany to something like insurancCompanyId and then call insurancecompany1 insuranceCompany.
I have two tables wherein i want to insert the data to the first one (MASTER) and the other table would copy some of the data from the Master table..
Here is my representation:
I want the Ven_ID to also be reflected in my Workflow table Workflow_ReqID automatically.
I know this is possible but can someone give me the directions ?
You can have a trigger/procedure at database level which will insert data into your second table. It depends if this table is updated anywhere else.
There are two ways to go about it :
Use SQL Server AFTER INSERT Trigger. You can find plenty of resources off the internet on how to create a trigger and how to declare its definition.
Another way to do it is through entity framework (I see you have tagged entityframework)
I will explain how you can use entity framework
Let's say you have the entity representing the WorkFlow table as WorkFlow and the table representing Ven (may be vendor) as Vendor.
Since you are having required foreign key in the WorkFlow table of the Vendor primary key, you must have a backing stub for that i.e. your WorkFlow table must have a virtual navigational property of type Vendor i.e.
public class WorkFlow
{
//other properties
public virtual Vendor Vendor{get;set;}
}
you just have to create WorkFlow object and the Vendor object (either create a new or retreive from db) and just assign it to the workflow object i.e.
WorkFlowObj.Vendor = objVendor
and EntityFramework will take care of rest.
I would prefer this way.
Though using triggers is not bad, but only problem with them is when you have to deploy, you must also deploy them triggers and every time you make changes to them, you must take care of them too.
If you want Ven_ID and Workflow_ReqID to be same get the Vent_ID in the output parameter in store procedure and pass it to the second table insert statement.
Get last inserted id using SCOPE_IDENTITY() after insertion and add it to workflow table. To save db trip you can use sproc for that.