C# 初始化实体的公共属性

C# 初始化实体的公共属性,c#,.net,inheritance,asp.net-core-2.0,C#,.net,Inheritance,Asp.net Core 2.0,我有很多实体模型,它们都有一些共同的属性,如下所示 CreatedOn 创造者 拉斯顿 最后修改 每次我需要在数据库中保存对象时,我都必须手动初始化这些属性。 我想要一个方法或一些基类,在这里我可以初始化这些属性,以避免反复编写相同代码的麻烦。 注意:我希望基类的泛型实现不带基类构造函数。 提前谢谢我个人会使用接口定义。您的实体都将实现一个接口,称为iAddieDead实体或您认为合适的任何名称。接口将把您的四个属性CreatedOn、CreateBy、LastModifiedOn、LastMo

我有很多实体模型,它们都有一些共同的属性,如下所示

CreatedOn 创造者 拉斯顿 最后修改 每次我需要在数据库中保存对象时,我都必须手动初始化这些属性。 我想要一个方法或一些基类,在这里我可以初始化这些属性,以避免反复编写相同代码的麻烦。 注意:我希望基类的泛型实现不带基类构造函数。
提前谢谢

我个人会使用接口定义。您的实体都将实现一个接口,称为iAddieDead实体或您认为合适的任何名称。接口将把您的四个属性CreatedOn、CreateBy、LastModifiedOn、LastModifiedBy声明为get和set。任何需要这些字段的实体都需要实现接口

然后,当您的记录更新到数据库时,检查对象是否实现了IAudienty接口,例如myRecord是否为IAuditedEntity。如果确实实现了接口,则将属性设置为适当的值

在这种情况下,最好将对象强制转换到接口中,以确保类型安全

e、 g.IAuditedEntity myObj.CreatedOn=DateTime.Now

此实现将允许您将创建的字段和修改的字段拆分为两个独立的接口-创建可以被视为修改,但修改不一定是创建操作


理论上,通过接口实现,您将能够将接口应用于不同的实体类型,但将初始化这些字段的代码保留在一个位置。

您不能使用实体类来实现这一点,原因有很多。CreatedOn可以通过默认值进行处理,但其余的则需要实体类永远不会拥有的知识,比如HttpContext.User,或者仅仅是它是否正在被修改或创建

相反,您需要将此功能构建到您的上下文中。首先,您应该让您的所有实体类实现一个特定接口,用于从特定基类继承。在这两种情况下,您都希望将这些属性添加到该属性中,这样就可以确保任何实现/派生类都将拥有这些属性

然后,您可以向上下文类添加一个私有方法,如:

private void PopulateAuditTrailProperties()
{
    var httpContextAccessor = this.GetService<IHttpContextAccessor>();
    var username = httpContextAccessor?.HttpContext.User.Identity.Name;

    foreach (var entry in ChangeTracker.Entries<IEntity>().Where(x => x.State == EntityState.Added))
    {
        entry.Entity.CreatedOn = DateTimeOffset.UtcNow;
        entry.Entity.CreatedBy = username;
    }

    foreach (var entry in ChangeTracker.Entries<IEntity>().Where(x => x.State == EntityState.Modified))
    {
         entry.Entity.ModifiedOn = DateTimeOffset.UtcNow;
         entry.Entity.ModifiedBy = username;
     }
}
最后,您需要在Startup.cs中添加一些内容:


我想要。。。那你为什么不建造它呢-欢迎来到stackoverflow。请花一分钟的时间,特别是如何做,以及相应的问题。根据您的问题,我只能假设您在编写基本构造函数时遇到困难。你能详细说明一下你想要实现什么,当你试图实现这个逻辑时你面临什么问题,这样我就不必假设了?
public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
    PopulateAuditTrailProperties();
    return base.SaveChanges(acceptAllChangesOnSuccess);
}

public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default)
{
    PopulateAuditTrailProperties();
    return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}
services.AddDbContext<MyContext>(o =>
    o.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))
        .UseInternalServiceProvider()); // Add this line
services.AddHttpContextAccessor();