Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在实体框架6中设置默认值(数据库优先)_C#_Entity Framework - Fatal编程技术网

C# 如何在实体框架6中设置默认值(数据库优先)

C# 如何在实体框架6中设置默认值(数据库优先),c#,entity-framework,C#,Entity Framework,背景:我正在开始一个项目,将使用Linq2Sql的web应用程序转换为使用实体框架(v6)。我对L2S有很多经验,但我对EF是全新的。由于我们的应用程序及其数据库已经存在,所以我们使用“数据库优先”的方法。此外,数据库也在不断发展,因此我们正在对模式进行更改,模型将从修改后的数据库中更新,每次都会为EF模型重新生成代码 对于我们的许多实体(数据库表),每当构造实体时,我们都会在代码中设置默认值。在Linq2Sql中,很容易:为实体定义一个分部类,并向该类添加一个方法,如下所示: 部分void O

背景:我正在开始一个项目,将使用Linq2Sql的web应用程序转换为使用实体框架(v6)。我对L2S有很多经验,但我对EF是全新的。由于我们的应用程序及其数据库已经存在,所以我们使用“数据库优先”的方法。此外,数据库也在不断发展,因此我们正在对模式进行更改,模型将从修改后的数据库中更新,每次都会为EF模型重新生成代码

对于我们的许多实体(数据库表),每当构造实体时,我们都会在代码中设置默认值。在Linq2Sql中,很容易:为实体定义一个分部类,并向该类添加一个方法,如下所示:

部分void OnCreated(){SomeProperty=SomeDefaultValue;}

每当Linq2Sql构造新的实体对象时,它都会调用您定义的OnCreated()方法,并根据需要设置默认值。它工作得很好

问题:在EF中,我看不到在数据库优先方案中实现这一点的方法

  • 如果我修改EF生成的模型代码,那么每当我们在数据库修订后更新模型时,模型代码都会被覆盖

  • 如果我在一个单独的文件中为实体定义了一个分部类并定义了一个构造函数,编译器会抱怨构造函数已经定义

  • 似乎也不支持L2S的onCreate()方法

有什么建议吗


编辑:谢谢大家的宝贵意见,但我想我需要指出一个重要的考虑因素:我的目标是使用数据库优先的方法并坚持下去,而不是先转换到代码。当数据库模式随时间变化时,我希望EF设计器(或POCO生成器或任何工具)更新我的EF实体类以匹配。在应用程序中构造类时,不会丢失初始化类属性所添加的所有内容。这在Linq2Sql中很容易,但我只是不认为有什么方法可以首先在EF数据库中实现这一点。欢迎所有建议

来自EF背景,我通常在代码第一次迁移中手动完成。在生成的迁移的up函数中,您可以执行如下操作

AddColumn("dbo.Person", "IsActive", c => c.Boolean(nullable: false, defaultValue: true));
AddColumn("dbo.Person", "Name", c => c.String(nullable: false, defaultValue: "Mirza"));
或者要添加默认SQL值,请使用

AddColumn("dbo.Person", "CreatedDate",
           c => c.String(nullable: false, defaultValueSql: "GETDATE()"));

然而,在我看来,这种方法有一个缺点,那就是您必须跟踪(无用的)迁移。

使用EF Reverse poco模板-它将从数据库中派生默认值。您可以重写分部类中的InitializePartial方法来设置代码中的默认值。

OP here–我对ErikEJ的答案给予了肯定,但我想回顾一下我在这个主题上学到的知识,与其他人分享。有三个目标:

  • 使用数据库优先的方法并坚持使用它,即使数据库模式随着时间的推移而改变。也就是说,让EF根据预先存在的数据库为每个数据库表实体生成代码,并在更改数据库时更新代码

  • 提供每次构造对象时初始化实体对象属性的机制,例如
    Employee.Dependents=1
    。(我知道可以通过数据库模式设置简单的默认值,但更复杂的初始化必须通过代码执行。)

  • 当数据库架构被更改并且EF重新生成模型代码时,必须保留自定义初始化代码

  • EF不提供在数据库第一个场景中每次构造实体对象时设置属性的方法。编辑EF生成的代码不起作用,因为每当EF在更改数据库架构后重新生成代码时,它都会被覆盖。到目前为止,我想到了四个解决办法:

  • 一个想法是为每个实体类添加一个具有多个默认零参数构造函数的构造函数。例如,
    c=newcustomer(x)
    而不是默认的
    c=newcustomer()
    。应用程序代码将调用新的构造函数,该构造函数将继承默认构造函数并添加其他代码来初始化类属性。这避免了重复默认构造函数,这是C#不允许的。新构造函数位于单独的分部类文件中,因此当EF从数据库生成更新的模型时,它不会被覆盖

    但是,存在一种风险,即应用程序程序员可能会意外调用默认构造函数,从而导致微妙的错误

  • 另一种解决方案是将实体类包装在另一个类中,例如,包装在
    Customer
    类周围的
    Customer2
    类。新类将继承原始类,并根据需要为任何属性添加初始化代码

    由于这些新类与原始实体类代码分开,因此EF在重新生成模型代码时不会覆盖它们。可以对顶级应用程序代码隐藏实体类,以避免意外引用原始类。如果是这样的话,这应该是一个很好的技术,尽管我还没有测试过它

  • 第三方工具EntityFramework Reverse POCO Generator提供了帮助。它像EF一样生成POCO模型代码,但它不是EF。它有一个生成分部类的选项,实体类包括一个
    InitializePartial()
    方法,非常类似于Linq2Sql的
    OnCreated()
    。我认为,随着时间的推移,数据库会发生变化,这将很好地用于重新生成代码。我在这里担心的是,这是一个第三方产品,它总是有被淘汰或不受支持的风险

  • 最后,您可以更改EF用于生成代码的模板。基本思想是让生成的代码将“
    partialvoid OnCreated()
    ”添加到每个类中,这样我们就可以使用
    namespace myApplication.MyModel
    {
      public partial class myEntityName
      {
        public myEntityName(bool InitialiseOnConstruct) : this()
        {
          if (InitialiseOnConstruct) 
          {
            this.property1 = defaultValue1;
            this.property2 = defaultValue1;     
          }
        }
      }
    }
    
    thisEntity = new EntityName(true);