使用Entity Framework设置SQL列的默认值
使用Entity Framework设置SQL列的默认值
我正在尝试使用Code-First EF6与默认的SQL值。\n例如,我有一个\"CreatedDate\"列/属性,非空,在SQL中具有默认值\"getdate()\"\n我如何在我的代码模型中表示这个?目前我有:\n
\n这样会起作用吗,或者我需要使用可空类型,即使实际列应该是非空的,这样当EF没有设置值时,它不会发送一个值:\n
\n还是有更好的解决方案?\n我不想让EF处理我的默认值 - 我知道这对我是可用的,但在我的当前情况下不可能。
问题出现的原因:
该代码是为了解决在使用Entity Framework与MySQL数据库时,实体类的属性无法获取到默认值的问题。在MySQL中,可以为列设置默认值,但是在Entity Framework中,通过读取实体类的属性时无法获取到这些默认值。因此,该代码通过查询information_schema.columns表来获取列的默认值,并将其设置到对应的实体属性或字段上。
解决方法:
该代码是一个扩展方法,可以将其添加到数据库的部分类中。它的作用是获取实体类对应的数据库表的列的默认值,并将这些默认值设置到实体类的属性或字段上。
具体实现步骤如下:
1. 获取实体类对应的表名。
2. 构造查询语句,查询information_schema.columns表,获取列名和默认值。
3. 使用Entity Framework的Database.SqlQuery方法执行查询语句,将查询结果转换为列表。
4. 遍历查询结果,对于每个列,默认值分别设置到实体类的属性或字段上。
代码中的DBDefaults类用于存储查询结果的列名和默认值。
文章内容如下:
在使用Entity Framework与MySQL数据库时,我们可能会遇到一个问题:无法获取到实体类属性的默认值。在MySQL中,可以为列设置默认值,但是在Entity Framework中,通过读取实体类的属性时无法获取到这些默认值。为了解决这个问题,我们可以使用下面的代码:
public static bool GetDBDefaults(object entity) { try { string table_name = entity.GetType().Name; string q = $"select column_name, column_default from information_schema.columns where column_default is not null and table_schema not in ('information_schema', 'sys', 'performance_schema', 'mysql') and table_name = '{table_name}' order by table_schema, table_name, ordinal_position;"; ListdbDefaults = new List (); using (DatabaseModelFull db = new DatabaseModelFull()) { dbDefaults = db.Database.SqlQuery (q).ToList(); } Type myType = entity.GetType(); IList props = new List (myType.GetProperties()); IList fields = new List (myType.GetFields()); foreach (var dbDefault in dbDefaults) { var prop = props.SingleOrDefault(x => x.Name == dbDefault.column_name); if (prop != null) { if (dbDefault.column_default.Equals("CURRENT_TIMESTAMP")) prop.SetValue(entity, System.Convert.ChangeType(DateTime.Now, prop.PropertyType)); else prop.SetValue(entity, System.Convert.ChangeType(dbDefault.column_default, prop.PropertyType)); continue; } var field = fields.SingleOrDefault(x => x.Name == dbDefault.column_name); if (field != null) { if (dbDefault.column_default.Equals("CURRENT_TIMESTAMP")) field.SetValue(entity, System.Convert.ChangeType(DateTime.Now, field.FieldType)); else field.SetValue(entity, System.Convert.ChangeType(dbDefault.column_default, field.FieldType)); } } return true; } catch { return false; } } public class DBDefaults { public string column_name { get; set; } public string column_default { get; set; } }
以上代码是一个扩展方法,可以将其添加到数据库的部分类中。它通过查询information_schema.columns表来获取列的默认值,并将其设置到对应的实体属性或字段上。
使用该方法可以解决实体类属性无法获取到默认值的问题,提供了一种简单的解决方案。
请注意,由于访问了database_schema,该方法可能不是最快的,并且需要确保实体类与表名相同(或者进行相应的修改)。
希望以上内容对大家有所帮助。
在Entity Framework中,设置SQL列的默认值可能会出现问题。下面是一个关于如何解决这个问题的答案,同时还提到了使用EF Core的解决方法。
在EF6中,可以使用Fluent API的HasDefaultValue方法来设置默认值。下面是一个示例代码:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity() .Property(b => b.Rating) .HasDefaultValue(3); }
如果需要设置NULL值作为默认值,可以使用HasDefaultValueSql方法:
.HasDefaultValueSql("NULL");
此外,还可以使用Migrations的Up和Down方法来修改默认值。需要注意的是,在修改默认值之前可能需要先删除索引。以下是一个示例代码:
public partial class RemovingDefaultToZeroPlantIdManualChange : Migration { protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.DropIndex( name: "IX_TABLE_NAME_COLUMN_NAME", table: "TABLE_NAME" ); migrationBuilder.AlterColumn( name: "COLUMN_NAME", table: "TABLE_NAME", nullable: true, //在Up方法中,指定一个新的defaultValue: defaultValueSql: "NULL", oldClrType: typeof(int)); migrationBuilder.CreateIndex( name: "IX_TABLE_NAME_COLUMN_NAME", table: "TABLE_NAME", column: "COLUMN_NAME" ); } protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropIndex( name: "IX_TABLE_NAME_COLUMN_NAME", table: "TABLE_NAME" ); migrationBuilder.AlterColumn ( name: "COLUMN_NAME", table: "TABLE_NAME", nullable: true, //在Down方法中,将defaultValue恢复为旧值: defaultValueSql: "0", oldClrType: typeof(int)); migrationBuilder.CreateIndex( name: "IX_TABLE_NAME_COLUMN_NAME", table: "TABLE_NAME", column: "COLUMN_NAME" ); } }
总结起来,使用Fluent API的HasDefaultValue方法可以设置SQL列的默认值,在EF Core中可以使用HasDefaultValueSql方法。此外,还可以使用Migrations的Up和Down方法来修改默认值。
问题的原因是在EF6中没有一个属性来定义用于某个属性默认值的数据库函数。解决方法是使用Computed
属性和Migrations
来指定默认的数据库函数。你可以运行一个迁移并手动修改它以包含默认的SQL函数。
首先,在你的C#类中定义一个计算属性,不需要可为空。然后运行迁移并手动修改它以包含默认的SQL函数。迁移的代码如下:
public partial class Initial : DbMigration { public override void Up() { CreateTable( "dbo.MyEntities", c => new { Id = c.Int(nullable: false, identity: true), Name = c.String(), Created = c.DateTime(nullable: false, defaultValueSql: "GetDate()"), }) .PrimaryKey(t => t.Id); } public override void Down() { DropTable("dbo.MyEntities"); } }
在迁移代码中,你会注意到defaultValueSql函数。这是使计算工作的关键。