为什么要在 UpdateAsync 上设置 CreationTime 和 CreatorUserId?

Why are CreationTime and CreatorUserId getting set on UpdateAsync?

我正在调用 UpdateAsync,但即使我没有传递这些值,它也会更新 CreationTimeCreatorUserId 列。它应该只更新所需的列。

{
  "testCode": "string",
  "testName": "string",
  "testDesc": "string",
  "id": 1
}
public async Task UpdateTest(TestDetailsDTO input)
{
    var classobj = ObjectMapper.Map<Test>(input);
    await UpdateAsync(classobj);
}
public class TestDetailsDTO : FullAuditedEntityDto
{
    public string TestCode { get; set; }
    public string TestName { get; set; }
    public string TestDesc { get; set; }
}

参数 inputUpdateTest 服务方法中获取 CreationTime

public class Test : FullAuditedEntity
{
    public const int NVarcharLength20 = 20;
    public const int NVarcharLength30 = 30;
    public const int NVarcharLength50 = 50;

    [Required]
    [MaxLength(NVarcharLength20)]
    public virtual string TestCode { get; set; }

    [Required]
    [MaxLength(NVarcharLength30)]
    public virtual string TestName { get; set; }

    [MaxLength(NVarcharLength50)]
    public virtual string TestDesc { get; set; }
}

当前流量:

  1. ObjectMapper.Map<Test>(input) 创建一个新的 Test 对象。
  2. CreationTimeCreatorUserIddefault(DateTime)default(long?)
  3. ABP 设置这些值。

正确流程:

  1. 从数据库中获取 classobj
  2. 恢复 CreationTimeCreatorUserId
  3. input 映射到 classobj

var classobj = repository.GetEntity(input.id); // 1
input.CreationTime = classobj.CreationTime;    // 2
input.CreatorUserId = classobj.CreatorUserId;  // 2
ObjectMapper.Map(input, classobj);             // 3

更好的设计:

  • 不要为 input 继承 FullAuditedEntityDto → 跳过第 2 步。

It's working, any other way around? Because it's calling extra GetEntity method.

另一种方法是attach。权衡是您必须显式映射,而不是 ObjectMapper.Map.

// Create new stub with correct id and attach to context.
var classobj = new Test { Id = input.Id };
repository.As<EfRepositoryBase<MyDbContext, Test>>().Table.Attach(classobj);

// Now the entity is being tracked by EF, update required properties.
classobj.TestCode = input.TestCode;
classobj.TestName = input.TestName;
classobj.TestDesc = input.TestDesc;

// EF knows only to update the properties specified above.
_unitOfWorkManager.Current.SaveChanges();