This one's driving me nuts.
I have a table with several columns and a Primary Key (bigint, not null)
I have VS create a model of it
public long ParcelRangeID { get; set; }
..
..
Then I create Controller and View. When I use the Create View to create a new record, on db.SaveChanges the troubles start: (I have included the field in my view as HiddenFor)
[Key]
, [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
and [HiddenInput(DisplayValue = false)]
[Bind(Exclude="ParcelRangeID")]
i get the DbUpdateConcurrencyException.How can I insert a new record and have the required ID generated automatically without the error?
Edit
Here's the controller code:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ParcelRange parcelrange)
{
if (ModelState.IsValid)
{
db.ParcelRange.Add(parcelrange);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(parcelrange);
}
And the model:
public partial class ParcelRange
{
public ParcelRange()
{
this.PickupAddressID = -1;
this.OrganizationID = -1;
this.DepotID = -1;
this.IsVTG = 0;
this.IsInternal = 0;
this.IsInterCompany = 0;
this.UpdateCount = 0;
this.IsActive = 1;
this.Modified = DateTime.Now.Date;
this.Created = DateTime.Now.Date;
this.ValidFrom = DateTime.Now.Date;
this.ValidTo = DateTime.MaxValue;
}
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
[Key]
[HiddenInput(DisplayValue = false)]
public long ParcelRangeID { get; set; }
public long NdswCustomerID { get; set; }
public long PickupAddressID { get; set; }
public long OrganizationID { get; set; }
public long DepotID { get; set; }
public string ParcelRangePrefix { get; set; }
public string ParcelNumberStart { get; set; }
public string ParcelNumberEnd { get; set; }
public byte IsVTG { get; set; }
public byte IsInternal { get; set; }
public byte IsInterCompany { get; set; }
public byte[] RowVer { get; set; }
public System.DateTime Created { get; set; }
public System.DateTime Modified { get; set; }
public int UpdateCount { get; set; }
public System.DateTime ValidFrom { get; set; }
public System.DateTime ValidTo { get; set; }
public byte IsActive { get; set; }
}
Edit (2)
And finally the (default) view autogenerated
@model MvcApplication1.ParcelRange
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
@using (Html.BeginForm()) {
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
@Html.HiddenFor(model => model.ParcelRangeID)
<fieldset>
<legend>ParcelRange</legend>
<div class="editor-label">
@Html.LabelFor(model => model.NdswCustomerID)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.NdswCustomerID)
@Html.ValidationMessageFor(model => model.NdswCustomerID)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.PickupAddressID)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.PickupAddressID)
@Html.ValidationMessageFor(model => model.PickupAddressID)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.OrganizationID)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.OrganizationID)
@Html.ValidationMessageFor(model => model.OrganizationID)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.DepotID)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.DepotID)
@Html.ValidationMessageFor(model => model.DepotID)
</div>
@* <div class="editor-label">
@Html.LabelFor(model => model.ParcelRangePrefix)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.ParcelRangePrefix)
@Html.ValidationMessageFor(model => model.ParcelRangePrefix)
</div>*@
<div class="editor-label">
@Html.LabelFor(model => model.ParcelNumberStart)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.ParcelNumberStart)
@Html.ValidationMessageFor(model => model.ParcelNumberStart)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.ParcelNumberEnd)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.ParcelNumberEnd)
@Html.ValidationMessageFor(model => model.ParcelNumberEnd)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.IsVTG)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.IsVTG)
@Html.ValidationMessageFor(model => model.IsVTG)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.IsInternal)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.IsInternal)
@Html.ValidationMessageFor(model => model.IsInternal)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.IsInterCompany)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.IsInterCompany)
@Html.ValidationMessageFor(model => model.IsInterCompany)
</div>
@* <div class="editor-label">
@Html.LabelFor(model => model.Created)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Created)
@Html.ValidationMessageFor(model => model.Created)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Modified)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Modified)
@Html.ValidationMessageFor(model => model.Modified)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.UpdateCount)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.UpdateCount)
@Html.ValidationMessageFor(model => model.UpdateCount)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.ValidFrom)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.ValidFrom)
@Html.ValidationMessageFor(model => model.ValidFrom)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.ValidTo)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.ValidTo)
@Html.ValidationMessageFor(model => model.ValidTo)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.IsActive)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.IsActive)
@Html.ValidationMessageFor(model => model.IsActive)
</div>*@
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
Edit (3) Database script for the table:
USE [DPDCDB_ODS]
GO
/****** Object: Table [dbo].[ParcelRange] Script Date: 16-6-2014 15:50:40 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[ParcelRange](
[ParcelRangeID] [bigint] IDENTITY(1,1) NOT NULL,
[NdswCustomerID] [bigint] NOT NULL,
[PickupAddressID] [bigint] NOT NULL,
[OrganizationID] [bigint] NOT NULL,
[DepotID] [bigint] NOT NULL,
[ParcelRangePrefix] AS (left([ParcelNumberStart],(4))),
[ParcelNumberStart] [nvarchar](50) NOT NULL,
[ParcelNumberEnd] [nvarchar](50) NOT NULL,
[IsVTG] [tinyint] NOT NULL,
[IsInternal] [tinyint] NOT NULL,
[IsInterCompany] [tinyint] NOT NULL,
[RowVer] [timestamp] NOT NULL,
[Created] [datetime] NOT NULL,
[Modified] [datetime] NOT NULL,
[UpdateCount] [int] NOT NULL,
[ValidFrom] [date] NOT NULL,
[ValidTo] [date] NOT NULL,
[IsActive] [tinyint] NOT NULL,
CONSTRAINT [PK_ParcelRange] PRIMARY KEY CLUSTERED
(
[ParcelRangeID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [DATA]
) ON [DATA]
GO
ALTER TABLE [dbo].[ParcelRange] ADD DEFAULT ((-1)) FOR [NdswCustomerID]
GO
ALTER TABLE [dbo].[ParcelRange] ADD DEFAULT ((-1)) FOR [PickupAddressID]
GO
ALTER TABLE [dbo].[ParcelRange] ADD DEFAULT ((-1)) FOR [OrganizationID]
GO
ALTER TABLE [dbo].[ParcelRange] ADD DEFAULT ((-1)) FOR [DepotID]
GO
ALTER TABLE [dbo].[ParcelRange] ADD DEFAULT ((0)) FOR [IsVTG]
GO
ALTER TABLE [dbo].[ParcelRange] ADD DEFAULT ((0)) FOR [IsInternal]
GO
ALTER TABLE [dbo].[ParcelRange] ADD DEFAULT ((0)) FOR [IsInterCompany]
GO
ALTER TABLE [dbo].[ParcelRange] ADD DEFAULT (getdate()) FOR [Created]
GO
ALTER TABLE [dbo].[ParcelRange] ADD DEFAULT (getdate()) FOR [Modified]
GO
ALTER TABLE [dbo].[ParcelRange] ADD DEFAULT ((0)) FOR [UpdateCount]
GO
ALTER TABLE [dbo].[ParcelRange] ADD DEFAULT (getdate()) FOR [ValidFrom]
GO
ALTER TABLE [dbo].[ParcelRange] ADD DEFAULT (CONVERT([date],'9999-12-31')) FOR [ValidTo]
GO
ALTER TABLE [dbo].[ParcelRange] ADD DEFAULT ((1)) FOR [IsActive]
GO
Edit (4)
I'm using Entity Framework 5.0, will try to update to a higher version.
Edit (5) Updated to EF 6.1, same problem This is my connectionstring:
metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient;provider connection string="data source=XXX.XXX.XXX.XXX\DEV;initial catalog=DPDCDB_ODS;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient
"(I have included the field in my view as HiddenFor)"
As it is a database-generated primary key, in a create
view it has no initial value and you should not be using a HiddenFor
to hold that property. Just delete that HiddenFor
.
If you use the scaffolding wizards to create EF controllers you should note the primary key is never present in the create
views.
I took the table script provided, created a database, exported it to Azure, created a VS 2013 MVC web application and then the EF model-based controller and views for the table. I then published it to Azure and it works just fine (well done Microsoft, let's see anyone do that with Amazon S3 in 5 mins flat!) :). I suspect it is the version of one of your libraries (maybe EF version). Otherwise it may be a side effect of other database activity on your web app.