"Cannot insert the value NULL into column" with a non-null value - c#

This is the code I have:
Controller action method:
[HttpPost]
public ActionResult Create(Goal goal)
{
if (ModelState.IsValid)
{
repository.SaveGoal(goal);
return View("Index");
}
else
{
return View(goal);
}
}
Model:
public class Goal
{
[Required]
public int GoalId { get; set; }
[Required]
public string Name { get; set; }
[Required]
[HiddenInput(DisplayValue = false)]
public decimal Latitude { get; set; }
[Required]
[HiddenInput(DisplayValue = false)]
public decimal Longitude { get; set; }
[Required]
public bool IsPrivate { get; set; }
}
Repository:
public class EFGoalRepository : IGoalRepository
{
private EFDbContext context = new EFDbContext();
public IQueryable<Goal> Goals
{
get { return context.Goals; }
}
public void SaveGoal(Goal goal)
{
context.Goals.Add(goal);
context.SaveChanges(); // the line which causes the exception
}
}
The problem: When I try to save a new Goal object with GoalId set to 0, I get the following error:
Cannot insert the value NULL into column 'GoalId', table 'TravelGoals.dbo.Goals'; column does not allow nulls. INSERT fails.
The statement has been terminated.
I'm still new at ASP.NET MVC, but I believe this worked when I tried it a month ago with a different project.
All the values in my Goal object are valid (non-null, Name is of correct length). The GoalId property is set to 0, so it is not null either. I thought that Entity Framework would automatically assign a value to it.
What can I do to make this work?

What I needed to do was setting the column as identity in SQL Server.
Probably the simplest way to do this (assuming you're using Visual Studio):
Open the SQL Server Object Explorer
Double-click the table you want to edit (or right-click and select View Designer)
Open the Properties window
Select the column in the Identity Column property as shown below

Problem is GoalId is not identity.Put this attribut on GoalId
[Key]
public int GoalId { get; set; }
If your EF version is lower than 5 use this:
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int GoalId { get; set; }

Related

Database reading to list<T> for display returning null values for some columns that already have values (asp.net mvc)

I have created a database for saving movie details using an ASP.NET MVC web application. I can add data to the database. Inside the database it is showing values in all columns. But when I retrieve data from the table using this statement
return cnn.Query<T>(sql).ToList();
the retrieved list contains null values for 6 columns (C_Category, FilmName, Filmid, D_Cost, P_Cost) [Poster is also null because I haven't added the code for converting the file upload to bytes. That is to be added] But these 6 columns have their respective values in the database.
Is there any way to correct my code to read from database properly? Can you please suggest anything?
I tried adding a breakpoint at the above return statement and viewed the list, which showed up the error values in it before it is passed to further stages. The project builds without any errors and runs but displays these nulls.
The following is the SQL Server data access class file's code
public static List<T> LoadData<T>(string sql)
{
using (IDbConnection cnn = new SqlConnection(GetConnectionSring()))
{
return cnn.Query<T>(sql).ToList();
}
}
This is my business logic class:
public static List<FilmAddModel> LoadFilm()
{
string sql = #"select * from dbo.Film;";
return SqlDataAccess.LoadData<FilmAddModel>(sql);
}
And this is my model for dB display and write
public class FilmAddModel
{
public int Filmid { get; set; }
public string FilmName { get; set; }
public string Actor { get; set; }
public string Actress { get; set; }
public string Pub_Date { get; set; }
public string Director { get; set; }
public string Producer { get; set; }
public decimal P_Cost { get; set; }
public decimal D_Cost { get; set; }
public string Category { get; set; }
public string C_Category { get; set; }
public byte[] Poster { get; set; }
}
Here's my home controller code to use the above for displaying the database contents:
public ActionResult ViewFilm()
{
ViewBag.Message = "Movies List";
var data = LoadFilm();
List<FilmAddModel> movies = new List<FilmAddModel>();
foreach (var row in data)
{
movies.Add(new FilmAddModel
{
Filmid = row.Filmid,
FilmName = row.FilmName,
Actor = row.Actor,
Actress = row.Actress,
Pub_Date = row.Pub_Date,
Director = row.Director,
Producer = row.Producer,
P_Cost = row.P_Cost,
D_Cost = row.D_Cost,
Category = row.Category,
C_Category = row.C_Category,
Poster = row.Poster
});
}
return View(movies);
}
Following is my database structure
CREATE TABLE [dbo].[Film]
(
[Film_id] INT IDENTITY (1, 1) NOT NULL,
[film_name] VARCHAR(50) NULL,
[actor] VARCHAR(50) NULL,
[actress] VARCHAR(50) NULL,
[pub_date] VARCHAR(50) NULL,
[director] VARCHAR(50) NULL,
[producer] VARCHAR(50) NULL,
[prod_cost] DECIMAL(18) NULL,
[dist_cost] DECIMAL(18) NULL,
[category] VARCHAR(30) NULL,
[cert_category] VARCHAR(20) NULL,
[poster] VARBINARY(MAX) NULL,
PRIMARY KEY CLUSTERED ([Film_id] ASC)
);
The names of your SQL Server table columns and your C# model class don't match - you have e.g. film_name in the table, and FilmName in the C# model class - same goes for cert_category in SQL Server, and C_Category in C#.
If you have such differences in name, you need to decorate your C# model class with data annotations - something like:
public class FilmAddModel
{
[Column("film_id")]
public int Filmid { get; set; }
[Column("film_name")]
public string FilmName { get; set; }
public string Actor { get; set; }
public string Actress { get; set; }
public string Pub_Date { get; set; }
public string Director { get; set; }
public string Producer { get; set; }
[Column("prod_cost")]
public decimal P_Cost { get; set; }
[Column("dist_cost")]
public decimal D_Cost { get; set; }
public string Category { get; set; }
[Column("cert_category")]
public string C_Category { get; set; }
public byte[] Poster { get; set; }
}
With these data annotations, the mapping should be done properly between the values in your SQL Server table, and the C# model class.
As a side note: the LoadFilm method returns a List<FilmAddModel> - so why are you creating a second List<FilmAddModel> in your ViewFilm action method and iterate over the list return to add the same type of data into the result list?? You could just simply return the data returned from LoadFilm - it's already in the "right" shape ....
When you converting data to model inside foreach loop you didn’t use the correct name for those field to retrive from database.
Use
C_Category = row.cert_category
Filmid = row.Film_id
etc.
that means according to fieldname inside your data object.

Adding more entries replaces everything instead of adding

Good day I am new in mongodb, I can successfully perform a CRUD, but now I want to dig deep into mongoDB. I have this JSON and I want it to update my database once it has a data, and create a new one if it doesn't exist, but what happens is it always replace my value for the "LeaderboardDetails".
Here is the MongoDB JSON:
{
"id" : "secretsomething",
"UserID" : "zgahsjd",
"category" : "testing",
"Score" : 2000,
"Badges" : 0,
"LeaderboardDetails": {
"id": "123123123213",
"ScoreForDay": 10000,
"BadgesForDay": 0
}
}
When I submit to update the "LeaderboardDetails" it should add a new entry if it doesn't exist, otherwise update the current one , but instead it replaces it.
Here is my code for PUT:
public void Update(string id, SomeModel newScore)
{
_record.ReplaceOne(scores => scores.id == id, newScore);
}
Here is the SomeModel Code:
[Required]
[JsonProperty(PropertyName = "UserID")]
public string UserID { get; set; }
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string id { get; set; }
[Required]
[JsonProperty(PropertyName = "category")]
public string category { get; set; }
[Required]
public int Score { get; set; }
[Required]
public int Badges { get; set; }
public class LeaderboardIDToSend
{
public string id;
public string ScoreForDay;
public string BadgesForDay;
public LeaderboardIDToSend(string _id, string _score, string _badges)
{
id = _id;
ScoreForDay = _score;
BadgesForDay = _badges;
}
}
[Required]
public LeaderboardIDToSend LeaderboardDetails;
Looking at your json, leaderBoardDetails is an object, but it should be a list of objects, that is the first modification you should do, second, in order for you to add an item to set, you should use Builders<T>.Update.AddToSet(c => c.leaderBoardDetails, leaderboardDto), now regarding your concern, you want to upsert the object, as far as I know, and looking at Array Update Operators, there is no such operator, so you will have to do this manually, you need to load all your existing leader, then check if this id exist, if so, you need to update its values, and then Update the whole list (leaderBoardDetails), if it doesn't exist, you can simple use AddToSet operator

How i can say EF6 not insert NULL value

I set deafaultValue in migration
AlterColumn("Users", "NotNullValue", c => c.String(nullable: false, defaultValue: "Work it!"));
then i try add new object, and SqlProfiler show me query
INSERT [dbo].[WowTable]([NotNullValue],[OnceMoreValue]) VALUES (NULL, 'val')
that throw "cannot insert the value null into column"
is that any way to stop inserting and updating property when it null?
UPD:
Domain class:
public class User
{
public string NotNullValue { get; set; }
public int Id { get; set; }
public string OnceMoreValue { get; set; }
}
Update method:
public Task AddOrUpdate<TEntity>(TEntity entity) where TEntity : class, IEntity
{
_dbContext.Set<TEntity>().AddOrUpdate(x => x.Id, entity);
return _dbContext.SaveChangesAsync();
}
calling:
AddOrUpdate(new User{OnceMoreValue = "val"});
You can either validate the model using [Required] attribute for NotNullValue property:
public class User
{
[Required]
public string NotNullValue { get; set; }
public int Id { get; set; }
public string OnceMoreValue { get; set; }
}
Ref: https://msdn.microsoft.com/en-in/data/gg193959.aspx
Or from what I see in your migration script, you have a default value for this property ("Work It"). So in your User class constructor, you can set NotNullvalue = "Work It" so that this default value will be saved in the case you mentioned:
AddOrUpdate(new User{OnceMoreValue = "val"});

Null list after query

I have a problem where I create an object containing a list, load it into my database, run a query that returns the object, but find the list null. All other properties of the object are as they should be. I'm using a list called "Ints" that is filled with a few integers but I've tried using other types.
Here's my model:
public class CourseModel
{
public int CourseModelId { get; set; }
public virtual ICollection<int> Ints { get; set; } // the variable in question
public string Name { get; set; }
public string Overview { get; set; }
}
And here's my database population (The database is called LearnYou):
public class LearnYouDbContextInitializer : DropCreateDatabaseAlways<LearnYouDbContext>
{
protected override void Seed(LearnYouDbContext context)
{
context.Courses.Add(new CourseModel()
{
Name = "C# Programming",
Overview = "You'll learn some C#",
Ints = new List<int> { 1, 42, 3 },
});
context.SaveChanges();
}
}
Here's the controller code for querying the object:
// GET: Course/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
CourseModel courseModel = db.Courses.Find(id);
// DEBUGGING THE PREVIOUS LINE SHOWS INTS IS NULL
if (courseModel == null)
{
return HttpNotFound();
}
return View(courseModel);
}
The "Ints" property is not null after saving the context in the database population part but is always null when it's queried (I visit the page ~Edit/1 to debug). I just can't figure out why when all other properties are fine. Any ideas? Thanks.
An ICollection in a model indicates a Parent->Child relationship. However, I doubt EF will be able to determine how to create a child table for an ICollection of integers. Here is what I would do.
Create a new model Ints (or whatever it actually represents):
public class Ints {
public int Value { get; set;}
}
Modify your original model to use it:
public class CourseModel
{
public int CourseModelId { get; set; }
public virtual ICollection<Ints> Ints { get; set; } // See the difference?
public string Name { get; set; }
public string Overview { get; set; }
}
That should make it work.
It Is not working because you are mapping directly to a int primitive type of .net and Entity Framework doesn't allow it.
In this case what you can do is create your onw object for example and sql table like
public class Ints {
{
public Course Course { get; set; }
public int IntValue { ger; set ; }
}
And referencing it from CourseModel
public virtual List<Ints> Ints { get; set; }

How to make SQL table property unique ( not repeatable)

Im new in MVC and im using Microsoft Visual Studio. So I have a controller to insert data into my SQL table with 4 properties ID Name Broi and Cena.
[HttpPost]
public ActionResult Table(ProductTable product)
{
if (!ModelState.IsValid)
{
return View(product);
}
using (var contex = new DefaultConnection())
{
contex.Products.Add(product);
contex.SaveChanges();
}
return View();
}
This is my producttalbe class:
[Table("ProductTable")]
public class ProductTable
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public string Name { get; set; }
public int Broi { get; set; }
public int Cena { get; set; }
}
But I want to make the Name property Unique so it will never repeat and if it repeats to call message in my View like "This Name already exists". I can see when making the table there is a property called "Not for replication" but I can't turn it to true it stays in gray and I can't change it.
try adding this attribute to your property:
[Unique(ErrorMessage="This Name already exists!")]
public string Name { get; set; }
here is how to implement the Unique attribute, and here is another extension code.

Categories

Resources