English 中文(简体)
How to set default value for POCO s in EF CF?
原标题:

In Entity Framework Code First approach, how do you set a default value for a property in the POCO s EntityConfiguration class?

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime CreatedOn { get; set; }
}

public class PersonConfiguration : EntityConfiguration<Person>
{
    public PersonConfiguration()
    {
        Property(p => p.Id).IsIdentity();
        Property(p => p.Name).HasMaxLength(100);

        //set default value for CreatedOn ?
    }
}
问题回答

With the release of Entity Framework 4.3 you can do this through Migrations.

EF 4.3 Code First Migrations Walkthrough

So using your example it would be something like:

public partial class AddPersonClass : DbMigration
{
    public override void Up()
    {
        CreateTable(
            "People",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    Name = c.String(maxLength: 100),
                    CreatedOn = c.DateTime(nullable: false, defaultValue: DateTime.UtcNow)
                })
            .PrimaryKey(t => t.Id);
    }

    public overide void Down()
    {
        // Commands for when Migration is brought down
    }
}

You can set the default values via the constructor for the class. Here is a class I have in my current project, using MVC3 and Entity Framework 4.1:

namespace MyProj.Models
{
using System;
using System.Collections.Generic;

public partial class Task
{
    public Task()
    {
        this.HoursEstimated = 0;
        this.HoursUsed = 0;
        this.Status = "To Start";
    }

    public int ID { get; set; }
    public string Description { get; set; }
    public int AssignedUserID { get; set; }
    public int JobID { get; set; }
    public Nullable<decimal> HoursEstimated { get; set; }
    public Nullable<decimal> HoursUsed { get; set; }
    public Nullable<System.DateTime> DateStart { get; set; }
    public Nullable<System.DateTime> DateDue { get; set; }
    public string Status { get; set; }

    public virtual Job Job { get; set; }
    public virtual User AssignedUser { get; set; }
}
}

I know this topic is going on for a while and I walked into some kind of the same issue. So far I couldn t find a solution for me that keeps the whole thing together at one place so the code is still readable.

At creation of an user I want to have some fields set by the object itself via private setters, e.g. a GUID and Creation Date and not polluting the constructor.

My User class:

public class User
{
    public static User Create(Action<User> init)
    {
        var user = new User();
        user.Guid = Guid.NewGuid();
        user.Since = DateTime.Now;
        init(user);
        return user;
    }

    public int UserID { get; set; }

    public virtual ICollection<Role> Roles { get; set; }
    public virtual ICollection<Widget> Widgets { get; set; }

    [StringLength(50), Required]
    public string Name { get; set; }
    [EmailAddress, Required]
    public string Email { get; set; }
    [StringLength(255), Required]
    public string Password { get; set; }
    [StringLength(16), Required]
    public string Salt { get; set; }

    public DateTime Since { get; private set; }
    public Guid Guid { get; private set; }
}

Calling code:

context.Users.Add(User.Create(c=>
{
    c.Name = "Name";
    c.Email = "some@one.com";
    c.Salt = salt;
    c.Password = "mypass";
    c.Roles = new List<Role> { adminRole, userRole };
}));

I m not sure as of what version of EF this becomes available, but as of version 5 for sure you can handle this. Just set a default value of GetDate() on the column in SQL, either in TSQL or the designer, then setup your EF classes as follows:

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime CreatedOn { get; set; }
}

public class PersonConfiguration : EntityConfiguration<Person>
{
    public PersonConfiguration()
    {
        Property(p => p.Id).IsIdentity();
        Property(p => p.Name).HasMaxLength(100);

        this.Property(p => p.CreatedOn ).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Computed);
    }
}

Note that you don t need to make the database column nullable, or the POCO property.

In the case where you want SQL Server to provide a default date the way you would accomplish this is, the important part is defaultValueSql: "GETDATE()" which will set the sql server default, not just evaluate to the time the script was run (i.e. DateTime.UtcNow)

   public partial class AddPersonClass : DbMigration
    {
    public override void Up()
    {
        CreateTable(
            "People",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    Name = c.String(maxLength: 100),
                    CreatedOn = c.DateTime(nullable: false, defaultValueSql: "GETDATE()")
                })
            .PrimaryKey(t => t.Id);
    }

    public overide void Down()
    {
        // Commands for when Migration is brought down
    }
}

There is no other way but to use DB MIGRATIONS and to enable the migrations you must set your property like this

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]        
    public DateTime CreatedOn { get; set; }

And after that once your database is created you must follow the following steps to enable the migrations. Go to Program Manager console and Execute the following commands one by ones command

  • PM> Enable-Migrations
  • PM> Add-Migration AlterMyTable Here AlterMyTable can be any name. this will create a file under newly added Migrations folder in your solution currentTimestamp_AlterMyTable.cs -Now copy the following to the Up method of currentTimestamp_AlterMyTable.cs
  • AlterColumn("Person", "CreatedOn", n => n.DateTime(nullable: false, defaultValueSql: "SYSUTCDATETIME()")); And after that execute the last command in your Program Manager Console
  • PM> Update-Database And now if you see the Person table in your database and then navigate to the CreatedOn column it should be having the Default value as SYSUTCDATETIME() i.e. now if you try to insert some data to this table your database will automatically update this column CreatedOn for you.




相关问题
Manually implementing high performance algorithms in .NET

As a learning experience I recently tried implementing Quicksort with 3 way partitioning in C#. Apart from needing to add an extra range check on the left/right variables before the recursive call, ...

Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

How do I compare two decimals to 10 decimal places?

I m using decimal type (.net), and I want to see if two numbers are equal. But I only want to be accurate to 10 decimal places. For example take these three numbers. I want them all to be equal. 0....

Exception practices when creating a SynchronizationContext?

I m creating an STA version of the SynchronizationContext for use in Windows Workflow 4.0. I m wondering what to do about exceptions when Post-ing callbacks. The SynchronizationContext can be used ...

Show running instance in single instance application

I am building an application with C#. I managed to turn this into a single instance application by checking if the same process is already running. Process[] pname = Process.GetProcessesByName("...

How to combine DataTrigger and EventTrigger?

NOTE I have asked the related question (with an accepted answer): How to combine DataTrigger and Trigger? I think I need to combine an EventTrigger and a DataTrigger to achieve what I m after: when ...

热门标签