如何设置阴影属性的默认值 [英] How to set default values for shadow property

查看:79
本文介绍了如何设置阴影属性的默认值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下实体:

public class Person
{
    public Guid Id { get; set; }

    public string Name { get; set; }
}

这是我的数据库上下文

public class PersonDbContext : DbContext
{
    private static readonly ILoggerFactory
        Logger = LoggerFactory.Create(x => x.AddConsole());

    public DbSet<Person> Persons { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder
            .UseLoggerFactory(Logger)
            .UseSqlServer(
                "Server=(localdb)\\mssqllocaldb;Database=PersonDb;Trusted_Connection=True;MultipleActiveResultSets=true");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder
            .Entity<Person>()
            .Property<DateTime>("Created")
            .HasDefaultValueSql("GETUTCDATE()")
            .ValueGeneratedOnAdd();

        modelBuilder
            .Entity<Person>()
            .Property<DateTime>("Updated")
            .HasDefaultValueSql("GETUTCDATE()")
            .ValueGeneratedOnAddOrUpdate();
    }
}

OnModelCreating 覆盖中可以看出,我正在将阴影属性更新/创建"添加到 Person 实体.

As can be seen from OnModelCreating override, I'm adding shadow properties Updated/Created to Person entity.

我将这些属性设置为使用SQL默认值填充

I set those properties to be populated with SQL default values

    添加值时
  • 已创建
  • 添加或更新值时
  • 已更新
  • Created when value is added
  • Updated when value is added or updated

下面是客户端代码

var personId = Guid.Parse("CF5EE27D-C694-408A-9F7B-080FF6315843");

using (var dbContext = new PersonDbContext())
{
    var person = new Person
    {
        Id = personId,
        Name = "New Person"
    };

    dbContext.Add(person);

    await dbContext.SaveChangesAsync();
}

using (var dbContext = new PersonDbContext())
{
    var person = dbContext.Persons.Find(personId);

    var personName = person.Name;

    person.Name = $"{personName} {DateTime.UtcNow}";

    dbContext.SaveChanges();
}

我可以确认插入新个人时,两个属性都设置为UTC日期.但是,在更新时,未设置 Updated 属性.

I can confirm that both properties are set to UTC date when inserting a new person. However, on update, Updated property is not being set.

这是生成的t-sql:

This is the t-sql generated:

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (1ms) [Parameters=[@p1='?' (DbType = Guid), @p0='?' (Size = 4000)], CommandType='Text', CommandTimeout='30']
      SET NOCOUNT ON;
      UPDATE [Persons] SET [Name] = @p0
      WHERE [Id] = @p1;
      SELECT [Updated]
      FROM [Persons]
      WHERE @@ROWCOUNT = 1 AND [Id] = @p1;

阅读

但是,如果您指定在添加时生成DateTime属性或更新,则必须设置一种生成值的方式.一种方法是配置GETDATE()的默认值(请参见默认值)以生成新行的值.然后,您可以使用数据库触发器以在更新期间生成值(例如以下示例触发器).

However, if you specify that a DateTime property is generated on add or update, then you must setup a way for the values to be generated. One way to do this, is to configure a default value of GETDATE() (see Default Values) to generate values for new rows. You could then use a database trigger to generate values during updates (such as the following example trigger).

我不明白 ValueGeneratedOnAddOrUpdate()的目的是什么,如果它的行为类似于 ValueGeneratedOnAdd(),我必须手动干预(创建触发器)设置此属性.

I don't get what's the purpose of ValueGeneratedOnAddOrUpdate() then, if it behaves like ValueGeneratedOnAdd() and I have to manually intervene (creating a trigger) to set this property.

实际上,如果我将 Updated shadow属性的定义更改为

Indeed, if I change the definition of Updated shadow property to

modelBuilder
    .Entity<Person>()
    .Property<DateTime>("Updated")
    .HasDefaultValueSql("GETUTCDATE()")
    .ValueGeneratedOnAdd();

并在 PersonDbContext

public override int SaveChanges()
{
    ChangeTracker.DetectChanges();

    foreach (var entry in ChangeTracker.Entries().Where(entity => entity.State == EntityState.Modified))
    {
        entry.Property("Updated").CurrentValue = DateTime.UtcNow;
    }

    return base.SaveChanges();
}

这可以完成预期的工作.

This does what is expected.

问题是-在EF Core中为阴影属性设置默认值的正确方法是什么.

So the question is - what's the proper way to set default values for shadow properties in EF Core.

这是我较大项目中的简化示例,因此对 OnModelCreating 覆盖中的实体使用 HasData 并不是一个好选择(由于许多实体).

This is simplified example from my bigger project, so using HasData on the entities in OnModelCreating override is not a good option (due to many entities).

我正在使用EF Core 3.1.1

I'm using EF Core 3.1.1

<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.1"/>

推荐答案

我发现讨论,指出名称 ValueGeneratedOnAddOrUpdate()不够描述性.

I found dicussion where it is pointed that name ValueGeneratedOnAddOrUpdate() is not descriptive enough.

@rowanmiller感谢您的快速回复!现在我知道它是如何工作的,但是我认为这有点令人困惑.命名为"ValueGeneratedOnAddOrUpdate"建议在插入和更新时实际生成一个值.

@rowanmiller Thanks for the quick reply! Now I know how it works, but I think it's a bit confusing. The naming "ValueGeneratedOnAddOrUpdate" suggests that a value actually is generated on insert and update.

文档说:添加时生成的值"添加时生成的值表示如果您不指定值,则会为你."

And the docs says: "Value generated on add" "Value generated on add means that if you don’t specify a value, one will be generated for you."

添加或更新时生成的值"添加或更新时生成的值表示每次保存记录都会生成一个新值(插入或更新)."

"Value generated on add or update" "Value generated on add or update means that a new value is generated every time the record is saved (insert or update)."

也许在文档中添加了一个部分,描述了您如何提供自己的文件价值生成器?

Maybe add a section in the docs that describes how you supply your own value generator?

但是,请遵循EF团队的建议 警告部分,并将手动步骤应用于

However, advice from EF team is to follow the warning section and apply manual steps to generate values for Update case manually.

@bcbeatty详细说明包含在主要部分中,在Fluent和Data Annotation部分中有一个警告框指向详细说明.

@bcbeatty the detailed explanation is included in the main section, and there is a caution box in the Fluent and Data Annotation sections that points back to the detailed note.

这只是让EF知道为添加的实体生成了值,它不能保证EF将实际机制设置为产生价值.有关更多详细信息,请参见添加时生成的值.

This just lets EF know that values are generated for added entities, it does not guarantee that EF will setup the actual mechanism to generate values. See Value generated on add section for more details.

因此,看来至少对于 DateTime 阴影属性,OP中的方法才是可行的方法.

So it seems, that at least for DateTime shadow properties, approach in OP is the way to go.

这篇关于如何设置阴影属性的默认值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆