43

En Entity Framework 4, Code Only (CTP3), ¿cómo establece un valor predeterminado para una propiedad en la clase EntityConfiguration de POCO?¿Cómo establecer el valor predeterminado para POCO en EF CF?

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 ? 
    } 
} 
+1

En caso de que alguien se pregunte. Termino usando 'Repository Pattern' (http://stackoverflow.com/questions/3175/repository-pattern-tutorial-in-c-sharp), estableciendo los valores predeterminados durante INSERT. Es una buena separación, ya que estoy pensando en alejarme de EF en el futuro. – Andy

+0

+1 por "alejarse de EF en el futuro". ¡Perdí un montón de tiempo que podría haber codificado SQL para mi aplicación actual! Pero, ¿qué vas a usar? NHibernate, ¿es mejor? – Mzn

Respuesta

4
+3

Código primero es todavía un CTP. Por favor, escriba un informe de Connect para esto, si aún no lo ha hecho. –

+0

En realidad, creo que fue una decisión de diseño activa. Establecer valores predeterminados en la base de datos es una especie de paso aparte del enfoque de solo código. –

+2

Bueno, espero que el "Código solo" signifique que todo está configurado en los códigos. Establecer manualmente el valor predeterminado en el archivo db no es una buena idea, ya que necesito el marco de la entidad para crear la base de datos utilizando la función context.CreateDatabase(), y realmente no quiero mantener ambos códigos y script db al mismo tiempo. – Andy

15

Puede establecer los valores predeterminados a través del constructor para la clase. Aquí es una clase que tengo en mi proyecto actual, utilizando MVC3 y 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; } 
} 
} 
+0

No creo que esto juegue bien con las propiedades virtuales, sin embargo ... – Gleno

+11

¿Qué sucede si el valor almacenado de la base de datos para 'HoursUsed' es 5.0? ¿El constructor sobrescribirá el valor de la base de datos? ¿O construirá primero y luego reemplazará el 0 predeterminado con el valor real? – Benjamin

24

Con el lanzamiento de Entity Framework 4.3 que puede hacer esto a través de las migraciones.

EF 4.3 Code First Migrations Walkthrough

Así, utilizando el ejemplo sería algo así como:

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 
    } 
} 
+1

¿Se puede usar 'AlterColumn' para modificar con éxito los valores predeterminados sin descartar y volver a crear la columna o la tabla? – Benjamin

+3

¿Hay alguna manera de hacerlo mediante la extensión de 'EntityTypeConfiguration'? Por ejemplo, cualquier cosa con un Guid siempre se predetermina a 'newsequentialid()'? – drzaus

+0

¿Cómo se hace esto si la columna de la tabla ya existe? – tofutim

7

Sé que este tema está pasando por un tiempo y entré en una especie de la misma cuestión. Hasta ahora no pude encontrar una solución para mí que lo mantenga todo junto en un solo lugar, por lo que el código aún es legible.

Al crear un usuario, quiero que el propio objeto establezca algunos campos a través del private setters, p. un GUID y fecha de creación y no 'contaminante' el constructor.

Mi clase Usuario:

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; } 
} 

Código de llamada:

context.Users.Add(User.Create(c=> 
{ 
    c.Name = "Name"; 
    c.Email = "[email protected]"; 
    c.Salt = salt; 
    c.Password = "mypass"; 
    c.Roles = new List<Role> { adminRole, userRole }; 
})); 
+1

Aprox interesante – GibboK

3

No estoy seguro como el de la versión de EF que estos estén disponibles, pero a partir de la versión 5 para asegurarse de que puede manejar esta. Sólo hay que establecer un valor por defecto de GetDate() en la columna en SQL, ya sea en TSQL o el diseñador, a continuación, configurar sus clases de EF de la siguiente manera:

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); 
    } 
} 

Tenga en cuenta que no es necesario para hacer la base de datos de la columna anulable , o la propiedad POCO.

+1

Creo que el punto es tener EF establecer el valor predeterminado al usar Code First, y no tener que entrar en SQL y configurarlo usted mismo. – Kyle

3

En el caso en que desee que SQL Server proporcione una fecha predeterminada de la manera en que lo haría, la parte importante es defaultValueSql: "GETDATE()" que configurará el servidor sql predeterminado, no solo evaluará la hora la secuencia de comandos se ejecuta (es decir 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 
    } 
} 
0

no hay otro camino que utilizar DB mIGRACIONES y permitir que las migraciones debe establecer su propiedad como esta

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

y después de eso una vez se crea su base de datos debe seguir los siguientes pasos para habilitar las migraciones. Ir al programa de consola Manager y ejecute los siguientes comandos uno por otras comando

  • PM> Enable-Migrations
  • PM> Add-Migration AlterMyTable Aquí AlterMyTable puede ser cualquier nombre. esto creará un archivo en la carpeta que acaba de agregar las migraciones en su solución currentTimestamp_AlterMyTable.cs -Ahora copiar el siguiente al método arriba de currentTimestamp_AlterMyTable.cs
  • AlterColumn("Person", "CreatedOn", n => n.DateTime(nullable: false, defaultValueSql: "SYSUTCDATETIME()")); Y después de eso ejecutar el último comando en el Administrador de programas de la consola
  • PM> Update-Database Y ahora si ve la tabla Person en su base de datos y luego navega hasta la columna CreatedOn debe tener el valor predeterminado como SYSUTCDATETIME() es decir, ahora si intenta insertar algunos datos en esta tabla su base de datos actualizará automáticamente esta columna CreatedOn para tú.
Cuestiones relacionadas