草庐IT

EF7创建模型值生成篇

OoO 2023-03-28 原文

在 EF7 中,生成的值是非常重要的,因为它们决定了数据库表中的数据。在本文中,我们将以人员为例,使用 Fluent API 展示所有 EF7 生成值的功能。
我们先来看一下人员表的属性:

public class Person
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public int NameLength { get; set; }
    public int Age { get; set; }
    public DateTime Birthday { get; set; }
    public DateTime CreationTime { get; set; }
    public DateTime LastUpdated { get; set; }
}

在EF7中,我们可以使用Fluent API来配置表的属性。下面,我们将展示所有生成值的功能,并提供相应的代码示例。

默认值

默认值是指当实体对象的属性没有设置值时,将使用的值。使用 HasDefaultValue 方法设置默认值:

builder.Property(p => p.CreationTime).HasDefaultValue(DateTime.Now); 

还可以使用 SQL 表达式为属性指定一个默认值:

builder.Property(e => e.CreationTime).HasDefaultValueSql("getdate()");

计算列

计算列是指在数据库中创建的一列,该列的值是由一系列计算表达式生成的。在 EF7 中,我们可以使用 HasComputedColumnSql 方法来创建计算列。例如,我们要将 Person 实体的 FullName 属性设置为由 FirstName 和 LastName 属性计算得出的值:

builder.Property(p => p.FullName)
    .HasComputedColumnSql("[FirstName] + ' ' + [LastName]");

HasComputedColumnSql 方法还有一个 stored 参数,当指定为 true 时,EF7 将在数据库中创建一个存储的计算列。这在插入新记录时,计算列的值将由数据库计算并存储在该列中,而不是每次查询时重新计算。以下代码将 Age 和 NameLength 属性设置为存储的计算列:

builder.Property(e => e.Age)
    .HasComputedColumnSql("[CreationTime].[Year] - [Birthday].[Year]", stored: true);

builder.Property(p => p.NameLength)
    .HasComputedColumnSql("LEN([LastName]) + LEN([FirstName])", stored: true);

显示配置值生成

显示配置值生成是指在 EF7 中明确指定生成的值。在 EF7 中,我们可以使用 ValueGeneratedOnAdd 方法允许我们指定属性的值在插入新记录时自动生成。例如,我们可以使用以下代码为 id 属性指定自增值:

builder.Property(p => p.Id).ValueGeneratedOnAdd(); 

有些需求是修改,我们可以使用 ValueGeneratedOnAddOrUpdate 方法允许我们指定属性的值在插入或更新记录时自动生成。例如,我们可以使用以下代码为 LastUpdated 属性指定默认值,并在插入或更新记录时自动生成 LastUpdated 的值:

builder.Property(e => e.LastUpdated).HasDefaultValueSql("getdate()")
    .ValueGeneratedOnAddOrUpdate();

自定义值生成

在某些情况下,我们可能希望在插入新记录时使用自定义的值生成策略。

builder.Property(p => p.Id)
    .HasValueGenerator<GuidValueGenerator>(); // 使用自定义的值生成器

public class GuidValueGenerator : ValueGenerator<Guid>
{
    public override bool GeneratesTemporaryValues => false;
    public override Guid Next(EntityEntry entry)
    {
        return Guid.NewGuid(); // 生成Guid值
    }
}

一般来说,EF数据库提供程序已经帮我们实现好了Guid的算法。使用显示值生成就可以,不需要自定义。
见这篇文章:《EF7数据库提供者的自定义值生成器》

替代值生成

在 EF7 中,当我们向数据库中插入一条新记录或更新现有记录时,如果某些属性的值未设置,则 EF7 会根据其配置生成默认值。然而,有时候我们可能希望在保存更改后保留属性的当前值而不是使用默认值,或者在属性的值未设置时抛出异常。
PropertySaveBehavior 枚举表示属性在保存更改时的行为。它有以下三个状态:

  1. Save:属性值应该被保留。
  2. Ignore:属性值应该被忽略。
  3. Throw:如果属性值未设置,则应该抛出异常。

SetAfterSaveBehavior保存更改前、SetBeforeSaveBehavior保存更改后方法允许我们为特定属性设置这些行为。
例如,我们可以使用以下代码为 LastUpdated 属性,虽然指定默认值是当前修改时间。但在保存更改前,未设置默认值,则抛出异常,而不会使用默认值:

builder.Property(b => b.LastUpdated).HasDefaultValue(DateTime.Now)
        .ValueGeneratedOnAddOrUpdate()
        .Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Throw);

无值生成

无值生成是指在 EF7 中不生成任何值。在 EF7 中,我们可以使用 ValueGeneratedNever 方法来设置无值生成。例如,我们要将 Person 实体的 Email 属性设置为不生成任何值:

builder.Property(p => p.Email).ValueGeneratedNever();

总结

在本文中,我们介绍了 EF7 中可用的各种生成值选项,并以人员为例演示了如何使用 Fluent API 配置这些选项。使用生成值选项可以使我们更方便地处理数据库相关任务。例如,我们可以使用默认值、计算列和自动生成值等选项来简化我们的代码,提高代码的可读性和可维护性。
在使用这些选项时,我们需要了解每个选项的用途和适用场景,以便选择合适的选项。在本文中,我们介绍了以下选项:

  • HasDefaultValue: 指定属性的默认值
  • HasDefaultValueSql: 使用 SQL 表达式指定属性的默认值
  • HasComputedColumnSql: 将属性指定为存储的计算列
  • HasComputedColumnSql stored: 将属性指定为计算列并将其存储在数据库中
  • ValueGeneratedOnAdd: 指定属性的值在插入新记录时自动生成
  • ValueGeneratedOnAddOrUpdate: 指定属性的值在插入或更新记录时自动生成
  • 自定义值生成
  • 替代值生成
  • 无值生成

通过使用这些选项,我们可以轻松地配置我们的实体模型,并使其更符合我们的业务需求。

有关EF7创建模型值生成篇的更多相关文章

  1. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  2. ruby - 如何在 Ruby 中顺序创建 PI - 2

    出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits

  3. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  4. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  5. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  6. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  7. ruby-on-rails - 无法使用 Rails 3.2 创建插件? - 2

    我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby​​1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在

  8. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  9. ruby - 在 jRuby 中使用 'fork' 生成进程的替代方案? - 2

    在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',

  10. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

随机推荐