我有很多实体模型,其中所有的实体模型都有一些共同的属性,如下所示。
每次我需要将对象保存在数据库中时,都必须手动初始化这些属性。 我想要一个方法或一些基类,在这些类中我可以初始化这些属性,从而避免了一次又一次编写相同代码的麻烦。 注意:我想要没有基本构造函数的基类的泛型实现。 预先谢谢你
答案 0 :(得分:3)
由于多种原因,您不能对您的实体类执行此操作。 public async Task<TwiMLResult> MyMethodName()
{
var response = new VoiceResponse();
var message = await _logic.GetMyLongText(); // This test I get from BL, it is an async method
response.Say(message);
var gather = new Gather(new [] {Gather.InputEnum.Speech}.ToList(), Url.ActionUri(nameof(AnotherMethodName), ControllerName), speechTimeout: "auto");
response.Append(gather);
response.Redirect(Url.ActionUri(nameof(IncorrectOrNoInputMethod), ControllerName));
return TwilioResultFrom(response);
}
可以通过默认值进行处理,但是其余的则需要实体类永远不会拥有的知识,例如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;
}
}
和SaveChanges
,以使每个方法在保存之前都调用此方法:
SaveChangesAsync
最后,您需要在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);
}
中添加一些内容:
Startup.cs
并且:
services.AddDbContext<MyContext>(o =>
o.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))
.UseInternalServiceProvider()); // Add this line
答案 1 :(得分:0)
我个人将使用接口定义。您的实体都将实现一个称为IAuditedEntity的接口(或您认为合适的任何名称)。该接口将声明您的四个属性(CreatedOn,CreateBy,LastModifiedOn,LastModifiedBy)为get和set。任何需要这些字段的实体都需要实现该接口。
然后在将记录更新到数据库时,检查对象是否实现IAuditEntity接口,例如如果(myRecord是IAuditedEntity)。如果确实实现了该接口,则将属性设置为适当的值。
在这种情况下,最好将对象强制转换为接口,以确保类型安全。
例如(((IAuditedEntity)myObj).CreatedOn = DateTime.Now。
此实现将允许您将创建和修改的字段拆分为两个单独的接口-create可以被视为修改,但是修改不一定是create操作。
从理论上讲,使用接口实现,您将能够将接口应用于不同的实体类型,但是将用于初始化这些字段的代码保留在一个地方。