I work on an Entity Framework 6.1.3, ASP.NET MVC 5, Code First with an existing databse project. My database (SQL Server 2016) includes a table that has a “rowguid” (uniqueidentifier, ROWGUIDCOL) column (as well as an ID primary key column) and a “ModifiedDate” (datetime, DEFAULT (getdate)) column. When trying to create a new record in browser the user is asked to type the rowguid and ModifiedDate values instead of the server applying them automatically. I tried a few tricks I could think of (I even created an AFTER UPDATE trigger in the table to set the date) but without success.
I then removed these fields from the table’s model class and created new views. This did the trick as now SQL Server inserts the values automatically. Unfortunately, I’m not anymore able to see these values in index, edit and details views.
What should I do so the column values are inserted automatically and still be able to see these values?
Well this the code for the "Title" table EF model (the applications name is HSEFCF):
namespace HSEFCF
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.Spatial;
[Table("Person.Title")]
public partial class Title
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Title()
{
People = new HashSet<Person>();
TitleLocales = new HashSet<TitleLocale>();
}
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public byte TitleID { get; set; }
public Guid rowguid { get; set; }
public DateTime ModifiedDate { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Person> People { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<TitleLocale> TitleLocales { get; set; }
}
}
The SQL code is this:
CREATE TABLE [Person].[Title](
[TitleID] [tinyint] IDENTITY(1,1) NOT NULL,
[rowguid] [uniqueidentifier] ROWGUIDCOL NOT NULL,
[ModifiedDate] [datetime] NOT NULL,
CONSTRAINT [PK_PersonTitle_PersonTitleID] PRIMARY KEY CLUSTERED
(
[TitleID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [Person].[Title] ADD CONSTRAINT [DF_PersonTitle_rowguid] DEFAULT (newid()) FOR [rowguid]
GO
ALTER TABLE [Person].[Title] ADD CONSTRAINT [DF_PersonTitle_ModifiedDate] DEFAULT (getdate()) FOR [ModifiedDate]
GO
I don't mind not being able to see the rowguid values but I'd like to be able to see the ModifiedDate values.
I removed the rowguid column from the model so now SQL insert the value itself (I don't mind being unable to see the actual values). I could do the same with ModifiedDate but then I wouldn't be able to see the values which it doesn't fit me. I then inserted the following code in my DbContext file but that it doesn't work. I get no error messages other than "The ModifiedDate field is required."
public override int SaveChanges()
{
DateTime saveTime = DateTime.Now;
foreach (var entry in this.ChangeTracker.Entries()
.Where(e => e.State == EntityState.Added))
{
if (entry.Property("ModifiedDate").CurrentValue == null)
entry.Property("ModifiedDate").CurrentValue = saveTime;
}
return base.SaveChanges();
}
This is the controller code:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using HSEFCF;
namespace HSEFCF.Controllers
{
public class TitleController : Controller
{
private HSEFCFContext db = new HSEFCFContext();
// GET: Title
public ActionResult Index()
{
return View(db.Titles.ToList());
}
// GET: Title/Details/5
public ActionResult Details(byte? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Title title = db.Titles.Find(id);
if (title == null)
{
return HttpNotFound();
}
return View(title);
}
// GET: Title/Create
public ActionResult Create()
{
return View();
}
// POST: Title/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "TitleID,ModifiedDate")] Title title)
{
if (ModelState.IsValid)
{
db.Titles.Add(title);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(title);
}
// GET: Title/Edit/5
public ActionResult Edit(byte? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Title title = db.Titles.Find(id);
if (title == null)
{
return HttpNotFound();
}
return View(title);
}
// POST: Title/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "TitleID,ModifiedDate")] Title title)
{
if (ModelState.IsValid)
{
db.Entry(title).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(title);
}
// GET: Title/Delete/5
public ActionResult Delete(byte? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Title title = db.Titles.Find(id);
if (title == null)
{
return HttpNotFound();
}
return View(title);
}
// POST: Title/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(byte id)
{
Title title = db.Titles.Find(id);
db.Titles.Remove(title);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
This is the Create view code:
@model HSEFCF.Title
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Title</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<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>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
And this is the Edit view code:
@model HSEFCF.Title
@{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Title</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.TitleID)
<div class="form-group">
@Html.LabelFor(model => model.ModifiedDate, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.ModifiedDate, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.ModifiedDate, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
Thanks in advance, galaf.