0

I am adding to an entity a property called DateCreated, which will be set programmatically. I want the update-database process to create a table column for it, as it does for all other properties. But I do not want it to create a date picker for it in the corresponding create view.

I believe the NotMapped attribute will exclude the property from the DB table completely

Example:

public class Person
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    //dont want this to show on Person create page, but should appear is DB table column
    public DateTime DateCreated { get; set; }
}
Progman
  • 16,827
  • 6
  • 33
  • 48
pnizzle
  • 6,243
  • 4
  • 52
  • 81
  • `But I do not want it to create a date picker for it in the corresponding create view`, clarify this please? – AMunim Aug 14 '22 at 06:38
  • @AMunim, by default, EFC will create a table for the entity model, and it will create table columns for the properties on the model. On the .cshtml view for creating an item, there will be components such as text fields etc. For datecreated there will be a date picker. I do not want the date picker there. I could edit it out, but there might be a more official way. – pnizzle Aug 14 '22 at 06:47
  • 2
    Add `JsonIgnore` attribute, but better to use DTO classes. – Svyatoslav Danyliv Aug 14 '22 at 07:29
  • It looks like you need [shadow properties](https://learn.microsoft.com/en-us/ef/core/modeling/shadow-properties#configuring-shadow-properties) – Alexander Petrov Aug 14 '22 at 10:18

3 Answers3

1

Create a DTO for it and exclude the date property

public class PersonDTO
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Now in your C# code you can simply convert it back to the person and set the date automatically.

Person p = dtoperson.Adapt<Person>(); //mapster example, you can use automapper optionally
p.DateCreated = DateTime.Now;

You can also set a default value to "CURRENT_TIMESTAMP" in your dbconfig, now when you create a new record, you shouldn't have to set it manually.

AMunim
  • 992
  • 6
  • 13
  • In this case, since the PersonDTO does not have the date created property, the database table also wont have the date created column. I need table to have the column. Unless I am missing something.. – pnizzle Aug 14 '22 at 06:50
  • PersonDTO is not for EFCore, you will fetch all the 'Person's from DB then convert them to 'PersonDTO's and return this to the client, which will also return you a PersonDTO that you transform back to Person. Please search the internet for DTOs, mapping etc so you have a better understanding why this is important and will solve too many of your problems – AMunim Aug 14 '22 at 06:55
  • I do know what DTO is, after you explained. I am a full stack dev and cannot specialise in subject terminology apologies. With your approach, the chtml view used for creating the Person is no longer the one auto generated by EFC, it would have to be a manually created one. I do not want to do that. The one created by EFC will still have the date created field on it. – pnizzle Aug 14 '22 at 07:25
  • I hope this helps, the view I am referring to when I say I do not want it to have a datepicker is the one EFCore automatically produces for the Entity, to allow entering first name, last name, and date created. – pnizzle Aug 14 '22 at 07:27
  • @pnizzle EF Core has nothing in common with your UI views - it's Object Relational Mapper which maps the database model to entity data model. Views (auto generated or not) are specific to the front end technology you are using - MVC, Blazor etc., so you really need to reword your question and use the appropriate terms/tags. – Ivan Stoev Aug 14 '22 at 08:12
  • @IvanStoev I could do that, but I am not familiar with the actual terminology you wish me to use. I understand your frustration, but we are not all experts at everything. That was the best I could word my question with the knowledge and experience I have gained so far in EFCore. I could go and learn EFCore for 3 months, but that defeats the purpose of StackOverflow. – pnizzle Aug 14 '22 at 08:19
  • @IvanStoev I will look into the bits you mentioned so I get a better understanding. Cheers for mentioning a few. For now I have a working solution, as posted. – pnizzle Aug 14 '22 at 08:30
  • 1
    @pnizzle You got me wrong, I am not frustrated at all. My previous comment was just for clarification for your follow up comments/questions on the posted answer. – Ivan Stoev Aug 14 '22 at 08:52
0

You could try [ScaffoldColumn] attribute, to avoid automatic generation of field, but also [Bindable(false)], to make sure that model binding engine never binds property coming from the (malicious) client:

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

public class Person
{
    [HiddenInput]
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    [ScaffoldColumn(false)]
    [Bindable(false)]
    public DateTime DateCreated { get; set; }
}

Another, often used attribute for scaffolding is [HiddenInput], usually used for auto-generated Ids.

If you are sending Person as JSON to the client, than you would also have to add one of this two attributes, depending which library does JSON serialization.

  • [System.Text.Json.Serialization.JsonIgnore]
  • [Newtonsoft.Json.JsonIgnore]

on DateCreated property.

Nenad
  • 24,809
  • 11
  • 75
  • 93
0

With guidance from a similar question, this works for what I am after:

public class Person
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    [Required, DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public DateTime DateCreated { get; set; }
}

//on migration
migrationBuilder.AlterColumn<DateTime>(name: "DateCreated", table: "Person", defaultValueSql: "GETDATE()");
    

This is working. DateCreated is not shown as a view component. DateCreated is shown in DB table, and is automatically set upon insertion.

pnizzle
  • 6,243
  • 4
  • 52
  • 81