【问题标题】:defaultValue in migration doesn't work迁移中的 defaultValue 不起作用
【发布时间】:2015-01-06 07:23:04
【问题描述】:

我有一个使用 EF 和代码优先的 MVC 项目。

我有一个模型 PropBase 和一个模型 MyProp - 它们被映射到同一个表(带有一个自动“鉴别器”列)。

我在 MyProp 中添加了两个属性——prop1 和 prop2:

   public class PropBase
   {
       public double Prop0 { get; set; }
   }

   public class MyProp: PropBase
   {
       public double Prop10 { get; set; }
       public double Prop1{ get; set; }    // new property
       public int Prop2{ get; set; }       // new property
   }

我还添加了一个新的迁移:

    public partial class AddProps12 : DbMigration
    {
        public override void Up()
        {
            AddColumn("dbo.Props", "Prop1", c => c.Double(nullable: true, defaultValue: 0));   
            AddColumn("dbo.Props", "Prop2", c => c.Int(nullable: true, defaultValue: 0));
        }

        public override void Down()
        {
            DropColumn("dbo.Props", "Prop1");
            DropColumn("dbo.Props", "Prop2");
        }
    }

但是当我运行应用程序时 - 新列添加了 null 并且就行了

  return m_myPropsRepository.AsQueryable().ToList();

我收到此错误

“MyProp”上的“Prop1”属性无法设置为“null”值。 您必须将此属性设置为“Double”类型的非空值。

我不能使用 nullable:false,因为当我向表中插入一个新的 PropBase 时 - 它不知道 Prop1 和 Prop2 并因此插入 NULL,然后我得到一个错误,因为我将它定义为不可为空。

我需要一种方法来实现它可以为空 AND 将 0 作为当前 MyProp 行的默认值。

【问题讨论】:

  • 什么意思'无论如何我都需要它,因为 PropBase 在同一个表中并且不包含 prop1 + prop2'
  • 表 Props 包含 PropBase 行和 MyProp 行。 PropBase 没有属性 prop1 和 prop2,因此 prop1 和 prop2 的列必须为 nullbale。它与 prop0 和我拥有的其他模型完美配合 - 但对于这些模型,表格是使用 CodeFirst 而不是手动迁移创建的。
  • 天哪,你是在一张桌子上使用 2 个实体吗?
  • 当然。我用它所有的时间。使用 CodeFirst 非常容易。 EntityFramework 只是自动添加“鉴别器”列,因此它知道每一行是什么类型。
  • @Mike - 看这里techiesweb.net/…

标签: c# entity-framework-5 entity-framework-migrations


【解决方案1】:

请尝试

AddColumn("dbo.Props", "Prop1", c => c.Double());   
AddColumn("dbo.Props", "Prop2", c => c.Int());
Sql("UPDATE dbo.Props SET Prop1 = 0, Prop2 = 0 WHERE Discriminator = 'MyProp'");

这个想法是用鉴别器“MyProp”更新数据库表中的旧值而不是空值

【讨论】:

  • 其实需要加上null,但是EF一定不能映射。数据库中除主键外的所有字段都必须可以为空。
  • @TamarG 请使用鉴别器“MyProp”从数据库表中删除旧值
  • 我无法手动执行任何操作,因为它也将安装在其他计算机上。
  • 谢谢!!终于有人理解我了:)这正是我所需要的。
  • @TamarG 不客气 :)
【解决方案2】:

好的...像下面这样使用

AddColumn("dbo.Props", "Prop2", c => c.Int(nullable: false, defaultValue: 0));

在你的代码中设置 nullable:false

【讨论】:

  • 当我写“nullable: false”和“defaultValue:0”时,它适用于当前行,但是当我尝试向表中添加一个新的 PropBase 行时 - 我收到一个错误,因为它向 Prop1 和 Prop2 插入 NULL(PropBase 不知道 Prop1 和 Prop2)。我需要一种方法使它可以为空并将 0 作为 defaultValue 放入当前的 MyProp 行
【解决方案3】:

您在数据库中将这两个字段添加为可为空(可为空:true),但您的模型(对象)将这些类型声明为不可为空。所以 EF 试图为非空属性分配一个空值。使对象属性 nuallbe 像这样:

public class MyProp: PropBase
{
   public double Prop10 { get; set; }
   public double? Prop1{ get; set; }    // new property
   public int? Prop2{ get; set; }       // new property
}

或者您必须使数据库中的列不为空(可为空:false)。

如果您希望它可以为空但仍需要默认值 0,那么您可以执行以下操作:

public class MyProp: PropBase
{
 private double? _prop1;
 private double? _prop2;

 public double Prop10 { get; set; }
 public double? Prop1
 {   
    get
    {
        if(!this._prop1.HasValue)
            this._prop1 = 0;

        return this._prop1;
    }
    set
    {
        this._prop1 = value;
    } 
 }
 public int? Prop2
 {   
    get
    {
        if(!this._prop2.HasValue)
            this._prop2 = 0;

        return this._prop2;
    }
    set
    {
        this._prop2 = value;
    } 
 }    
}

【讨论】:

  • 您是否在将其更改为 false 后重新运行迁移?
  • 是的。无论如何 - nullable:false 对我没有帮助。我需要此列可以为空,因为此表也适用于 PropBase,并且 PropBase 不使用 prop1 和 prop2。例如,Prop0 现在在表中可以为空(我使用了自动迁移)。
  • 那么你必须让你的对象属性可以为空。仅当列(在数据库中)被标记为不为空时,指定默认值才有效。如果将列标记为不可为空并指定默认值,则 PropBase 不需要它们。 EF 抱怨 db 列类型和对象的属性类型之间存在类型不匹配。两者都不能为空,或者两者都必须可以为空。
  • 如果我写“nullable: false”和“defaultValue:0”它可以工作 - 但是当我试图向表中添加一个新的 PropBase 行时 - 我收到一个错误,因为它插入 NULL Prop1 和 Prop2(PropBase 不知道 Prop1 和 Prop2)。
  • 我需要一种方法使它可以为空,并将 0 作为 defaultValue 放入当前的 MyProp 行。
猜你喜欢
  • 2023-03-14
  • 2012-09-08
  • 2017-06-18
  • 1970-01-01
  • 2017-09-04
  • 1970-01-01
相关资源
最近更新 更多