I am using ASP.Net MVC 5 with EF6
I have a model called DoodleBug (dont ask). When I try to create and save a new entry of this entity to the database I get the following exception, even though i am not inputting an Id value?
SqlException: Cannot insert explicit value for identity column in table
'DoodleBugs' when IDENTITY_INSERT is set to OFF.
Here is my model
public class DoodleBug
{
public int Id { get; set; }
public string Sentence { get; set; }
public DateTime Adate { get; set; }
public Boolean TrueFalse { get; set; }
public int DoodleId { get; set; }
public int BugId { get; set; }
public virtual Doodle Doodle { get; set; }
public virtual Bug Bug { get; set; }
}
Here is the controller
// GET: DoodleBugs/Create
public ActionResult Create()
{
ViewBag.Id = new SelectList(db.Bug, "Id", "BugString");
ViewBag.Id = new SelectList(db.Doodle, "Id", "DoodleString");
return View();
}
// POST: DoodleBugs/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Sentence,Adate,TrueFalse,DoodleId,BugId")] DoodleBug doodleBug) // Edited FROM [Bind(Include = "Id,Sentence,Adate,TrueFalse,DoodleId,BugId")] ---- removed Id from bind list
{
if (ModelState.IsValid)
{
db.DoodleBug.Add(doodleBug);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.Id = new SelectList(db.Bug, "Id", "BugString", doodleBug.Id);
ViewBag.Id = new SelectList(db.Doodle, "Id", "DoodleString", doodleBug.Id);
return View(doodleBug);
}
and here is the view
<div class="form-horizontal">
<h4>DoodleBug</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#*<div class="form-group">
#Html.LabelFor(model => model.Id, "Id", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("Id", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Id, "", new { #class = "text-danger" })
</div>
</div>*#
<div class="form-group">
#Html.LabelFor(model => model.Sentence, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Sentence, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Sentence, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Adate, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Adate, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Adate, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.TrueFalse, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.TrueFalse)
#Html.ValidationMessageFor(model => model.TrueFalse, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.DoodleId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.DoodleId, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.DoodleId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.BugId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.BugId, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.BugId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
In case it helps, here is the EF generated migration code for the DoodleBug Entity. I manually changed some of the codelines, as noted by the comments next to them, to create a Foreign Key relationship between the DoodleBug entity and two other entities (Doodle and Bug)
CreateTable(
"dbo.DoodleBugs",
c => new
{
Id = c.Int(nullable: false, identity: true), // Edited FROM 'Id = c.Int(nullable: false)'
Sentence = c.String(),
Adate = c.DateTime(),
TrueFalse = c.Boolean(),
DoodleId = c.Int(nullable: false),
BugId = c.Int(nullable: false),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.Bugs", t => t.BugId) // Edited FROM 'ForeignKey("dbo.Bugs", t => t.Id)'
.ForeignKey("dbo.Doodles", t => t.DoodleId) // Edited FROM 'ForeignKey("dbo.Doodles", t => t.Id)'
.Index(t => t.Id)
.Index(t => t.BugId) // Added
.Index(t => t.DoodleId); // Added
NB the controller and the view were scaffolded by EF which added both a Bind attribute for the ID in the create() method and a SelectList of items for the Id in the controllers ViewBag, as well as a form control in the view to utilise the SelectList from the controller to create a dropdown list of option to input into the Id value.
I have deleted the Id from the Bind attribute in the controllers Create() method and have commented out the form control in the View relating to the Id value (as seen by the #* - *# from lines 5 - 11 in the View)
Despite this when I run the code and try to submit the form I get the above error?
When I run the app in debug mode the properties box for the doodleBug variable has an Id value of 0 (Int). I'm not sure where this is coming from or if it a default value?
In response to questions below are the Doodle and Bug Models
public class Doodle
{
public int Id { get; set; }
public string DoodleString { get; set; }
public DateTime DoodleTime { get; set; }
public Boolean DoodleBool { get; set; }
public virtual DoodleBug DoodleBUg { get; set; }
}
public class Bug
{
public int Id { get; set; }
public string BugString { get; set; }
public DateTime BugTime { get; set; }
public Boolean BugBool { get; set; }
public virtual DoodleBug DoodleBug { get; set; }
}
I also have some fluent API attempting to create a 1 - to - 0/1 relationship, the DoodleBug Entity being the optional entity to both.
// 1 - 2 - 0/1
modelBuilder.Entity<DoodleBug>()
.HasRequired(db => db.Doodle)
.WithOptional(d => d.DoodleBUg);
modelBuilder.Entity<DoodleBug>()
.HasRequired(db => db.Bug)
.WithOptional(b => b.DoodleBug);
Not sure if this is what you mean by asking what my DB structure is but copied this from opening up sqlexpress;
dbo.DoodlBugs
Columns:
Id (PK, int, not null)
Sentence (nvarchar(max), null)
Adate (datetime, null)
TrueFalse (bit, null)
DoodleId (FK, int, not null)
BugId (FK, int, not null)
Keys
PK_dbo.DoodleBugs
FK_dbo.DoodleBugs_dbo.Bugs_BugId
FK_dbo.DoodleBugs_dbo.Doodles_DoodleId
As I mentioned in the comments, the fact that you had to modify manually the generated migration is indication of a problem in the model.
For instance this edit
Id = c.Int(nullable: false, identity: true), // Edited FROM 'Id = c.Int(nullable: false)'
The migration is generated based on the model. The important thing to notice here is that from EF point of view, the Id field is not identity. Although your edit fixed the database field, still for EF this field is not identity, hence EF does not treat it as identity and associated behaviors like not passing a value when doing INSERT, but like regular int field and passes its value (even it's 0 by default) to INSERT command, which leads to the exception you are getting.
Similar, the following edits
.ForeignKey("dbo.Bugs", t => t.BugId) // Edited FROM 'ForeignKey("dbo.Bugs", t => t.Id)'
.ForeignKey("dbo.Doodles", t => t.DoodleId) // Edited FROM 'ForeignKey("dbo.Doodles", t => t.Id)'
indicate that for EF DoodleId and BugId are not FKs (instead, Id is), so all the behavior and generated SQL joins will be based on that.
With that being said, never edit migrations manually to "fix" model issues, but fix the model.
The root of the problem in your case are the two one-to-one relationships. By default, EF uses so called Shared Primary Key Associations for such relationships, where the PK of the dependent table is also a FK to the principal table. And of course the PK of the dependent table is no more identity.
How to fix it? The problem is that one-to-one FK associations have limited support. More specifically, explicit FK properties are not supported. So you have to remove them from the model and keep only the navigation properties:
public class DoodleBug
{
public int Id { get; set; }
public string Sentence { get; set; }
public DateTime Adate { get; set; }
public Boolean TrueFalse { get; set; }
public virtual Doodle Doodle { get; set; }
public virtual Bug Bug { get; set; }
}
and change the configuration as follows:
modelBuilder.Entity<DoodleBug>()
.HasRequired(db => db.Doodle)
.WithOptional(d => d.DoodleBUg)
.Map(c => c.MapKey("DoodleId"));
modelBuilder.Entity<DoodleBug>()
.HasRequired(db => db.Bug)
.WithOptional(b => b.DoodleBug)
.Map(c => c.MapKey("BugId"));
Now the generated migration (w/o edits!) is:
CreateTable(
"dbo.DoodleBug",
c => new
{
Id = c.Int(nullable: false, identity: true),
Sentence = c.String(),
Adate = c.DateTime(nullable: false),
TrueFalse = c.Boolean(nullable: false),
BugId = c.Int(nullable: false),
DoodleId = c.Int(nullable: false),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.Bug", t => t.BugId)
.ForeignKey("dbo.Doodle", t => t.DoodleId)
.Index(t => t.BugId)
.Index(t => t.DoodleId);
I was receiving this error. In my case I changed the column on database (setting Identity) after I created with scaffolding the context in the MVC app. So I needed to remove this line from the DataContext class
entity.Property(e => e.Id).ValueGeneratedNever();
And this solve my problem! Good luck!
I have the following viewmodel in my mvc project.
public class AddGISViewModel
{
public myproject.Models.DomainModels.GIS gis { get; set; }
public IEnumerable<myproject.Models.DomainModels.Companies> Companies { get; set; }
public long CompanyID { get; set; }
}
I have created a view as this
#model myproject.ViewModels.GIS.AddGISViewModel
#using (Ajax.BeginForm("Create", "GIS", new AjaxOptions { HttpMethod = "Post", Url = "/GIS/Create" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.Label("company", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.CompanyID, new SelectList(Model.Companies, "CompanyID", "Name"), "select company please ", htmlAttributes: new {#class = "form-control" })
#Html.ValidationMessageFor(model => model.CompanyID)
</div>
</div>
also I have created following metadata
[Required(ErrorMessage = "you should select company")]
[DisplayName("company")]
[Display(Name = "company")]
public long CompanyID { get; set; }
When I run my project #validationmessagefor show 'CompanyID is a required field' not 'you should select company' that I define in metadata. How can I fix this problem?
You have created a view model, so apply those attributes to the property in the view model. Since the purpose of a view model is to represent what you want to display/edit in the view there is no point creating a separate class for metadata.
Your view model should be
public class AddGISViewModel
{
[Required(ErrorMessage = "you should select company")]
[DisplayName("company")]
public long? CompanyID { get; set; }
public IEnumerable<SelectListItem> Companies { get; set; }
....
}
Note that the CompanyID property should be nullable to protect against under-posting attacks, and the collection property for displaying the companies n the dropdownlist should be IEnumerable, so that the view is
#Html.DropDownListFor(model => model.CompanyID, Model.Companies, "select company please ", new { #class = "form-control" })
In addition, view models should not contain data models if your editing any properties of that model. If so replace GIS gis with each property of GIS that you need in the view.
Trying to get familiar with EF model, but I am having trouble at this point - foreign key problem.
So I have two models.
public class Employee
{
[Key]
public int EmpId { get; set; }
public string Name { get; set; }
public int WorkingDateTimeId { get; set; }
public virtual WorkingDateTime WorkingDateTimes { get; set; }
}
public class WorkingDateTime
{
[Key]
public int WorkingDateTimeId { get; set; }
public string Day { get; set; }
}
Creating Employee information works fine. So in my create view, I enter Employee Name, and WorkingDateTime information, which surprised me it automatically creates a row in WorkingDateTime table.
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.WorkingDateTimes.Day, "Day: ", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.WorkingDateTimes.Day, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
However, when I try to edit the specific Employee row, I get this error:
Cannot add or update a child row: a foreign key constraint fails ("test"."employees", CONSTRAINT "FK_Employees_WorkingDateTimes_WorkingDateTimeId" FOREIGN KEY ("WorkingDateTimeId") REFERENCES "workingdatetimes" ("WorkingDateTimeId") ON DELETE CASCADE O)
I am binding these properties in my controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "EmpId,Name,WorkingDateTimes")] Employee employee)
What do I need in order to Edit successfully?
I am currently new to Asp.net MVC .In one of the view I add a dropdownlist and I bind this dropdownlist with my database like this
Controller CollegeController
[HttpGet]
public ActionResult Create()
{
IEnumerable<SelectListItem> items = db.College_Names.Select(c => new SelectListItem { Value = c.id.ToString(), Text = c.Name });
IEnumerable<SelectListItem> item = db.Stream_Names.Select(c => new SelectListItem { Value = c.id.ToString(), Text = c.Stream });
ViewBag.CollName=items;
ViewBag.StreamName = item;
return View();
}
[HttpPost]
public ActionResult Create(College college)
{
try
{
if(ModelState.IsValid)
{
db.Colleges.Add(college);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.CollName = db.Colleges;
return View(college);
}
catch
{
return View();
}
}
This is my model
public class College
{
[Required]
public int Id { get; set; }
[Required]
[Display(Name="College Name")]
public int CollegeName { get; set; }
[Required]
public int Stream { get; set; }
[Required]
[Column(TypeName="varchar")]
public string Name { get; set; }
....
public virtual College_Name College_Name { get; set; }
public virtual Stream_Name Stream_Name { get; set; }
}
This is My View
<div class="form-group">
#Html.LabelFor(model => model.CollegeName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("CollName", (IEnumerable<SelectListItem>)ViewBag.CollName, "Select College", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.CollegeName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Stream, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("StreamName", (IEnumerable<SelectListItem>)ViewBag.StreamName, "Select Stream", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Stream, "", new { #class = "text-danger" })
</div>
</div>
Now when I check my database after I save the CollegeName and Stream in the database is zero from the dropdownlist.
You have multiple problems with your code. Firstly you dropdownlists are binding to a properties named CollName and StreamName which do not even exist in your model.
Next you cannot name the property your binding to the same as the ViewBag property.
Your view code would need to be (and always use the strongly typed xxxFor() HtmHelper methods
#Html.DropDownListFor(m => m.CollegeName, (IEnumerable<SelectListItem>)ViewBag.CollName, "Select College", new { #class = "form-control" })
....
#Html.DropDownListFor(m => m.Stream, (IEnumerable<SelectListItem>)ViewBag.StreamName, "Select Stream", new { #class = "form-control" }
and in your POST method, the values of college.CollegeName and college.Stream will contain the ID's of the selected options.
You also need to repopulate the ViewBag properties when you return the view in the POST method (as you did in the GET method) or an exception will be thrown (and note that your current use of ViewBag.CollName = db.Colleges; will also throw an exception)
I also strongly suggest you start learning to use view models (views for editing should not use data models - refer What is ViewModel in MVC?) - and use naming conventions that reflect what your properties are, for example CollegeNameList, or CollegeNames, not CollName
Right now I have added a Region to the ApplicationUser model in Identity 2.0
On the UsersAdmin view, Edit action, I have the following stock code to display/edit the Region of the User:
<div class="form-group">
#Html.LabelFor(model => model.Region, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Region, new { #class = "form-control" })
</div>
</div>
How do I make that TextBox into a DropDownList that allows the user to choose from a list of Region names where Regions is part of ApplicationDbContext?
public class Region
{
[Key]
public Guid ID { get; set; }
public string Name { get; set; }
public Company Company { get; set; }
public Region()
{
this.ID = Guid.NewGuid();
}
}
You could use a view model. In order to render a dropdown you need 2 properties in your view model: a scalar property to hold the selected value and a collection property to represent the list of possible values to be displayed:
public class MyViewModel
{
public Guid SelectedRegionID { get; set; }
public IEnumerable<SelectListItem> Regions { get; set; }
}
That your controller action will populate and pass to the view:
public ActionResult Index()
{
var viewModel = new MyViewModel();
viewModel.Regions = db.Regions.ToList().Select(x => new SelectListItem
{
Value = x.ID.ToString(),
Text = x.Name,
});
return View(viewModel);
}
and in the corresponding strongly typed view you could use the DropDownListFor helper:
#model MyViewModel
<div class="form-group">
#Html.LabelFor(model => model.Region, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.SelectedRegionID, Model.Regions, new { #class = "form-control" })
</div>
</div>