How to have default values for an attribute in Code First? - asp.net

Basically I'm trying to expand on the already created SimpleMembership of ASP.NET MVC 4.
I wanna add a balance field that has the initial value of 0.
I've tried with the following code and inserting nothing in the Balance field:
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public string RealName { get; set; }
public int Balance { get; set; }
}
But unfortunately I get an exception when I try to create a new user (without a balance) that I cannot insert null in balance since it doesn't allow nulls.
How can I get balance to be 0 as a default value in Code First.

The
int Balance
does not allow nulls but
int? Balance
does.
If you want to controll the structure at the database level, use explicit migrations and manually tweak the generated migration code so that you set up a default value at the database level. If you want a default value at the code level, just set the value in the default constructor of the class.

First: You can use a constructor like this:
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public string RealName { get; set; }
public int Balance { get; set; }
public UserProfile()
{
this.Balance = 0;
}
}
Second, clean and rebuild solution, then use the migration command
Update-database -verbose

Integers have a default value of 0 by default. When you instantiate a new UserProfile, Balance should already be set to 0.
See: Default Values Table (C# Reference)

Related

Cannot generate Id using Data annotation (EF6)

I'm new at EF6 and Asp.net MVC5.
There's problem of generating a unique ID automatically when I try to create my entities using the code first approach.
Consider an entity like this:
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int PostId { get; set; }
[Required]
[MaxLength(100), MinLength(5)]
public string Title { get; set; }
public string Content { get; set; }
public string Thumbnail { get; set; }
public string Description { get; set; }
public DateTime DateCreated { get; set; }
When I put [DatabaseGenerated(DatabaseGeneratedOption.Identity)] on PostId or even remove it. I was always get an exception error like this:
“Cannot insert the value NULL into column ‘PostId'”.
“column does not allow nulls. INSERT fails.
I don't know why EF6's always try to insert a null value to the Id column.
Then later, I found a solution.
I changed
DatabaseGeneratedOption.Identity to DatabaseGeneratedOption.None
and the problem was solved.
However, this solution doesn't seem to work like I expected.
the values inserted to the column are always the same. It's not unique.
With EF core, everything is just simple, I don't need DatabaseGenerated,just leave it to convention. But with EF6, I'm stuck. What I want is the Id field must be unique and increase everytime it inserted to the database.
Can someone please help me this?
I'm new to EF also, but I just create an Id field and it is inserted automatically by SQL Server, such as this model in my current project. The Id field populates as expected when I add new rows:
public class BlogPosts
{
public int Id { get; set; }
[Required]
public string Title { get; set; }
[Required]
public string ShortPost { get; set; }
[Required]
public string Post { get; set; }
[Required]
public string Tags { get; set; }
[Required]
public DateTime Updated { get; set; }
}
When you apply DatabaseGeneratedOption.Identity to your key property you are telling EF that the database will generate the identity. From the error it sounds like your database PostId column is not configured as an identity or primary key.
If you manually created the table and columns in the database you should ensure the configuration is at least compatible, or you should use migrations to ensure the database is configured in a good state for your EF model.

EF Core - Identity field suddenly jumped by 1000 and not able to search with Id

I am having a problem with primary key/Id of one table in a project.
In this table, the Id suddenly jumped from 38 to 1039.
Now the real issue is, when i find the entity by 1039 it doesn't exists but finding it by 39 gives me the entity.
I am not sure about this behaviour and hence not able to find the solution.
My model
public class Domain : Entity
{
public string Name { get; set; }
public string Description { get; set; }
}
public abstract class Entity
{
public int Id { get; set; }
public DateTime InsertDate { get; set; }
public DateTime? UpdateDate { get; set; }
public DateTime? DeleteDate { get; set; }
public bool IsDeleted { get; set; }
}
Method is like this...
public async Task<Response> Delete(int id)
{
var domain = await DataContext.Domains.FindAsync(id);
if (domain == null)
{
return new Response(ResponseType.NotFound);
}
}
Can anyone please help ?
it depend from Database setting IDENTITY-CACHE.
Identity cache store some values of a identity columns in case of SQL CRASH during a transaction or similar.
To avoid gaps in an identity column, you need to set IDENTITY-CACHE to OFF running this command on a SQL query window:
ALTER DATABASE SCOPED CONFIGURATION SET IDENTITY_CACHE = OFF
GO
you will find more informations here:
https://social.technet.microsoft.com/wiki/contents/articles/40666.sql-server-2017-identity-cache-feature.aspx

Tree structure with reference to root in Entity Framework

I'm trying to model a tree structure for orders in Entity Framework. Right now I've go the following:
public class ProjectModel
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int CustomerId { get; set; }
public virtual List<ProjectNode> Nodes { get; set; }
}
public class ProjectNode
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public string Path { get; set; }
public int? ParentId { get; set; }
[ForeignKey("ParentId")]
public virtual List<ProjectNode> Children { get; set; }
}
What I need to be able to do is get a reference to the root ProjectModel at any level of ProjectNode in order to authorize a given user actually having permission to view and change the project which contains the ProjectNode.
public class ProjectNode {
public int ProjectId { get; set; } //<-- this
...
public class ProjectModel {
[Key]
public int Id { get; set; } //<-- containing the value of this
}
My question is whether its possible to have a theoretical ProjectId property populated at every level of the tree structure, or if I need to set it manually.
I had something working that at first blush appeared to allow this functionality, but upon further investigation only populated the ProjectId for ProjectNodes contained in the ProjectModel's Nodes property.
It seems to me like it would be super inefficient to recurse backwards through the structure to get to the root.
Credit due to #TestWell for this answer -
Apparently, all I needed to do for EF to automatically populate the ProjectId property on the ProjectNode was to change the name of the Id property in ProjectModel to ProjectId.
Unfortunately, this doesn't appear to work if I add a CustomerId property to the ProjectNode that I would like automatically populated from the property of the same name on the node's root ProjectModel, which I realized is the more efficient solution to what I'm trying to do.

Set default datetime value with PetaPoco

I have a PetaPoco class which defines a database table. It looks like this:
namespace MyProject.Pocos
{
[TableName("AdminNotification")]
[PrimaryKey("id", autoIncrement = true)]
[ExplicitColumns]
public class AdminNotification
{
[Column("id")]
[PrimaryKeyColumn(AutoIncrement = true)]
public int id { get; set; }
[Column("dateTime")]
public DateTime dateTime { get; set; }
[Column("adminNotificationTypeId")]
public int adminNotificationTypeId { get; set; }
}
}
It works great except for one thing. In the database table itself (in SQL Server Express) there is a default value set for 'dateTime' - it defaults to (getdate()). However, when record is inserted using the PetaPoco class in my code, the value of dateTime is always NULL.
How can I set the default value in the PetaPoco class to the current date/time?
Thanks!
One way is to add a constructor and set the default value there:
[TableName("AdminNotification")]
[PrimaryKey("id", autoIncrement = true)]
[ExplicitColumns]
public class AdminNotification
{
[Column("id")]
[PrimaryKeyColumn(AutoIncrement = true)]
public int id { get; set; }
[Column("dateTime")]
public DateTime dateTime { get; set; }
[Column("adminNotificationTypeId")]
public int adminNotificationTypeId { get; set; }
public AdminNotification(){
dateTime = DateTime.Now;
}
}
Depending on the way you create and insert the object, the value will be showing the time of creation of the AdminNotification, not the time it has actually been written to the database, but most of the time the difference is negligible and won't make a difference.

Getting "Cannot insert the value NULL into column" when trying to save with .Add() method using DbContext . Please check my POCO's and save method

Used code first and everything appears to work apart from the below which also worked before when I used ObjectContext and called context.PCBuilds.AddObject(pcBuild) but after switching to DbContext it's giving me the error.
EFDbContext context = new EFDbContext();
public ActionResult Index()
{
PCBuild pcBuild = new PCBuild();
pcBuild.BuildID = 34245;
pcBuild.BuildName = "Test99";
pcBuild.MarkUp = 25;
pcBuild.BDetails = new List<BDetail>();
context.PCBuilds.Add(pcBuild);
//repository.PCBuilds.Attach(pcBuild);
context.SaveChanges();
return View();
}
Giving me the: Cannot insert the value NULL into column 'BuildID', table 'C:\USERS\ADMIN\DOCUMENTS\VISUAL STUDIO 2010\PROJECTS\NEOCART\NEOCART.WEBUI\APP_DATA\NEODBX.MDF.dbo.PCBuilds'; column does not allow nulls. INSERT fails. Where as BuildID was clearly set before the SaveChanges is called. Appears that calling the .Add(pcBuild) doesn't add the populated object for some reason and when savechanges is called it attempts to insert an empty PCBuild ?
Here are the POCO's
public class PCBuild
{
[Key]
public int BuildID { get; set; }
public string BuildName { get; set; }
public string Socket { get; set; }
public decimal? MarkUp {get; set;}
[InverseProperty("PCBuild")]
public virtual ICollection<BDetail> BDetails { get; set; }
}
public class BDetail
{
[Key]
public int LineID { get; set; }
[ForeignKey("PCBuild")]
public int BuildID { get; set; }
[ForeignKey("Product")]
public int ProductID { get; set; }
public bool? IsSelected { get; set; }
[InverseProperty("BDetails")]
public virtual PCBuild PCBuild { get; set; }
[InverseProperty("BDetails")]
public virtual Product Product { get; set; }
}
Use StoreGeneratedAttribute on the PCBuild.BuildID property. It is not only a key but IDENTITY field.
UPDATE
Actually, it should be [DatabaseGenerated(DatabaseGenerationOption.Identity)] annotation. The article linked above describes early CTP version.
UPDATE 2
Wait, the key is being generated by the app, it is not an identity column in database? Change annotation to [DatabaseGenerated(DatabaseGenerationOption.None)], re-create the context and rebuild the application.
I'm not really familiar with the Code First approach, but could it be that when you specify the BuildID as being a [Key] field, it is setting it as an auto identity field in the database?
As such it may be blocking your attempt to write to it.
Try removing the [Key] identifier, then recreate the database. Can you then save the object ok?

Resources