【问题标题】:Entity Framework migration automatically sets defaults实体框架迁移自动设置默认值
【发布时间】:2016-09-01 00:52:31
【问题描述】:

我在 PostgreSQL 数据库上使用 Entity Framework 6 和 Npgsql 提供程序。我有一个从此类创建的代码优先迁移:

public class CarriedItem : IItem {
    [Key, Required, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int CarriedItemId { get; set; }
    [Required]
    public int Size { get; set; }

    [Required]
    public string Name { get; set; }
    public string Description { get; set; }
    [Required]
    public bool GameOrPay { get; set; }
    [Required]
    public string Cost { get; set; }
}

我生成了迁移文件并创建了表,但我注意到数据库中的所有Required 属性都被赋予了默认值,这使得从数据库中强制执行NOT NULL 限制变得更加困难。所以在迁移中,我在列上设置了defaultValueSql 属性。

CreateTable(
    "dbo.CarriedItems",
    c => new {
        CarriedItemId = c.Int(nullable: false, identity: true),
        Size = c.Int(nullable: false, defaultValueSql: "1"),
        Name = c.String(nullable: false, defaultValueSql: null),
        Description = c.String(),
        GameOrPay = c.Boolean(nullable: false, defaultValueSql: null),
        Cost = c.String(nullable: false, defaultValueSql: null),
    })
    .Index(c => c.Name, unique: true)
    .PrimaryKey(t => t.CarriedItemId);

我删除并重新创建了数据库并再次运行迁移。它似乎没有任何区别。我可以查看它在 PGAdmin 中生成的表,并看到默认值仍然设置在 NOT NULL 列上:

CREATE TABLE dbo."CarriedItems"
(
  "CarriedItemId" serial NOT NULL,
  "Size" integer NOT NULL DEFAULT 1,
  "Name" text NOT NULL DEFAULT ''::text,
  "Description" text,
  "GameOrPay" boolean NOT NULL DEFAULT false,
  "Cost" text NOT NULL DEFAULT ''::text,
  CONSTRAINT "PK_dbo.CarriedItems" PRIMARY KEY ("CarriedItemId")
)
WITH (
  OIDS=FALSE
);

有没有可以用来阻止默认值的设置?我希望表格看起来像这样:

CREATE TABLE dbo."CarriedItems"
(
  "CarriedItemId" serial NOT NULL,
  "Size" integer NOT NULL DEFAULT 1,
  "Name" text NOT NULL,
  "Description" text,
  "GameOrPay" boolean NOT NULL,
  "Cost" text NOT NULL,
  CONSTRAINT "PK_dbo.CarriedItems" PRIMARY KEY ("CarriedItemId")
)
WITH (
  OIDS=FALSE
);

【问题讨论】:

  • 你的问题我不清楚。你需要自己设置默认值还是什么?如果一个字段是required,那么您不能为该字段设置NULL 值。
  • 我认为你是在使用TPH (CarriedItem : IItem) 的问题TPH,多个类共享同一个表。想想这个用例:“A”是一个需要属性 TestProp 的类,数据库如何将此列限制为只读,如果另一个继承类尝试添加新行会发生什么?如果您需要更多信息,请查看本节“TPH 要求子类中的属性在数据库中可以为空”weblogs.asp.net/manavi/…
  • @Sampath 如果该字段为空,我希望数据库抛出一个错误,以便任何访问数据库的应用程序在必填字段为空时都无法保存记录。可能存在其他应用程序未在模型中的属性上设置Required 属性的情况。如果他们将GameOrPay 字段留空,应用程序将不会抛出错误,并且数据库将默认为 false。这可能会导致问题。
  • @BassamAlugili IItem 是一个接口,所以它不应该使用 TPH。我不确定是否有实现 TPH 要求的幕后东西,因为它看到了这种联系。但是我有其他模型,例如 Job 模型,它不使用任何接口,并且在数据库中自动给定 DEFAULT[Required] 属性。
  • 对不起,但我认为@Sampath 有权利不清楚你想做什么?如果您在字段上输入 required => Not Null 是正确的。如果您不需要默认值,则可以将其删除。如果你想要Required并允许空字符串,那么你可以使用这个数据注释======> [Required(AllowEmptyStrings = true)]

标签: c# entity-framework postgresql npgsql


【解决方案1】:

看迁移源码,方法AppendColumn,你的情况大概是这样的

else if (column.IsNullable != null 
    && !column.IsNullable.Value 
    && (column.StoreType == null || 
    (column.StoreType.IndexOf("rowversion", StringComparison.OrdinalIgnoreCase) == -1))) 
{ 
    sql.Append(" DEFAULT "); 
    AppendValue(column.ClrDefaultValue, sql); 
} 

所以如果你指定 storeType 它应该可以工作。

【讨论】:

  • 如果我将名称列编辑为Name = c.String(nullable: false, storeType: "character varying"),它现在仍然添加默认值:"Name" character varying NOT NULL DEFAULT ''::character varying
  • 可能是您使用了不同版本的提供程序。仍在查看源代码(github.com/npgsql/EntityFramework6.Npgsql/blob/dev/src/…),您可以尝试将默认值设置为 null。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-09
  • 2016-07-15
  • 1970-01-01
  • 2012-05-12
  • 2012-07-25
  • 2013-07-13
相关资源
最近更新 更多