当前位置:网站首页>Entity Framework core captures database changes
Entity Framework core captures database changes
2022-04-23 17:20:00 【Meow】
Form writing habits together ! This is my participation 「 Nuggets day new plan · 4 Yuegengwen challenge 」 Of the 21 God , Click to see the event details .
In actual projects, we often need to record the changes of data stored in the database ( For example, record the original value of the data before modifying the data ), In this way, the data can be restored to the state before the change in case of misoperation , It can also be traced back to the person who modified the data . Most developers define their own code to record data changes , But this not only takes time and effort, but also affects the performance of the business . Of course , We can also use database triggers to record these operations , stay SQL Server database 2017 The above version provides us with the function of tracking database data changes , Using this function can accurately record the changes of database data . Although this function is powerful, sometimes the database we use is not SQL Server database , Or in some cases we are not suitable to use SQL Server This function provided by database . So what to do at this time ? If you're using Entity Framework Core 2.0 And above to develop the project , Then the problem will be solved . stay Entity Framework Core in , As long as the data change record is captured , We can restore the data to the state before the change at any time , Here the database change record is called audit data . So let's look at two questions first :
- When is the audit data generated and written to the database ?
- How are the old and new values of data obtained ?
To answer these two questions , Then follow me to see how to use Entity Framework Core To capture audit data .
zero 、 Create an audit model
The first step in capturing audit data and storing it in a database is to create an audit model , Only audit data with audit model can be stored in database correctly .
public class Audit
{
public int Id { get; set; }
public string TableName { get; set; }
public DateTime DateTime { get; set; }
[NotMapped]
public Operation Operation { get; set; }
public string OperationString
{
get { return Operation.ToString(); }
private set { Operation = (Operation)Enum.Parse(typeof(Operation), value, true); }
}
public string Key { get; set; }
public string Old { get; set; }
/// <summary>
/// Data after operation
/// </summary>
public string New { get; set; }
}
/// <summary>
/// Operation type
/// </summary>
public enum Operation
{
Add = 0,
Delete = 1,
Modified = 2
}
Copy code
The audit model created by the above code contains the name of the table to be operated TableName 、 Type of operation Operation 、 Primary key of the operated data Key 、 Data before operation Old And the data after the operation New , The operation type includes addition, deletion and modification .
One 、 Create audit data store
Now we have the audit model , But audit model is not the only way , We also need to create classes related to storing audit data , Let's create this class together .
public class AuditDb
{
public EntityEntry _entityEntry { get; set; }
public AuditDb(EntityEntry entityEntry)
{
this._entityEntry = entityEntry;
}
public string TableName { get; set; }
public Operation Operation { get; set; }
public Dictionary<string, object> keys { get; } = new Dictionary<string, object>();
public Dictionary<string, object> olds { get; } = new Dictionary<string, object>();
public Dictionary<string, object> news { get; } = new Dictionary<string, object>();
public List<PropertyEntry> propertyEntries { get; } = new List<PropertyEntry>();
public bool HasPropertyEntries => propertyEntries.Any();
public Audit ToAudit()
{
Audit audit = new Audit
{
TableName = TableName,
Operation = Operation,
DateTime = DateTime.Now,
Key = JsonConvert.SerializeObject(keys),
Old = olds.Count == 0 ? null : JsonConvert.SerializeObject(olds),
New = news.Count == 0 ? null : JsonConvert.SerializeObject(news)
};
return audit;
}
}
Copy code
This class is mainly used to store table names , Primary key of the operated data Id, Data before being operated and data after being operated . Our primary key will be seen in our operation code above Id、 The variables of the data before and after the operation are defined as dictionary types , This is because there may be problems with batch operation in our program . After converting the above information into Audit Prompt us to judge the length of the data before and after the operation , This is because when we add new data, there is no old data , When we submit data without making any changes to the data, there is no new data .
Two 、 rewrite SaveChanges
This example rewrites SaveChanges , about SaveChangesAsync The same applies . We need to be in OnBeforSaveBehavior Create in method AuditDb list .
public class EFContext : DbContext
{
public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
List<AuditDb> auditDbs = OnBeforeSaveBehavior();
var result = base.SaveChanges(acceptAllChangesOnSuccess);
return result;
}
List<AuditDb> OnBeforeSaveBehavior()
{
ChangeTracker.DetectChanges();
List<AuditDb> auditDbs = new List<AuditDb>();
foreach (EntityEntry entity in ChangeTracker.Entries())
{
if (entity.Entity is Audit || entity.State == EntityState.Detached || entity.State == EntityState.Unchanged)
{
continue;
}
AuditDb auditDb = new AuditDb(entity)
{
TableName = entity.Metadata.Name
};
auditDbs.Add(auditDb);
foreach (var property in entity.Properties)
{
if (property.IsTemporary)
{
auditDb.propertyEntries.Add(property);
continue;
}
var propertName = property.Metadata.Name;
if (property.Metadata.IsPrimaryKey())
{
auditDb.keys[propertName] = property.CurrentValue;
continue;
}
switch (entity.State)
{
case EntityState.Deleted:
auditDb.Operation = Operation.Delete;
auditDb.olds[propertName] = property.OriginalValue;
break;
case EntityState.Modified:
if (property.IsModified)
{
auditDb.Operation = Operation.Modified;
auditDb.olds[propertName] = property.OriginalValue;
auditDb.news[propertName] = property.CurrentValue;
}
break;
case EntityState.Added:
auditDb.Operation = Operation.Add;
auditDb.news[propertName] = property.CurrentValue;
break;
}
}
}
List<Audit> audits = new List<Audit>();
foreach (var item in auditDbs.Where(p => !p.HasPropertyEntries))
{
audits.Add(item.ToAudit());
}
return auditDbs.Where(p => p.HasPropertyEntries).ToList();
}
}
Copy code
up to now , All code to capture audit data is complete , One thing to note here is that some entity properties are generated by the database , For example, the current date 、Id etc. , These values need to wait SaveChanges After the method is executed, you can get , That is to say, in this case, the audit data must be saved in SaveChanges After method .
3、 ... and 、 summary
Through the previous code example and explanation , We can then answer the two questions raised earlier , Except when part of the data is automatically generated by the database , Most of the time, I call SaveChanges Before method , We go through... In the context ChangeTracker Property to get old and new values and save . The above code is easy to understand , For the most part , It can be used directly in the project .
版权声明
本文为[Meow]所创,转载请带上原文链接,感谢
https:https://yzsam.com/html/dWoJql.html
边栏推荐
- For the space occupation of the software, please refer to the installation directory
- Detailed explanation of C webpai route
- Lock锁
- JSON deserialize anonymous array / object
- ClickHouse-SQL 操作
- 快时钟同步慢时钟域下的异步控制信号slow clk to fast clk
- Milvus 2.0 质量保障系统详解
- Using quartz under. Net core -- operation transfer parameters of [3] operation and trigger
- Manually implement simple promise and its basic functions
- Shell-cut命令的使用
猜你喜欢

ASP. Net core JWT certification

Perception of linear algebra 2

Document operation II (5000 word summary)

ASP. Net core dependency injection service life cycle

Bottom processing of stack memory in browser

Shell脚本——Shell编程规范及变量

2.Electron之HelloWorld

. net cross platform principle (Part I)

1-1 NodeJS

快时钟同步慢时钟域下的异步控制信号slow clk to fast clk
随机推荐
Baidu Map Case - Zoom component, map scale component
Get the column name list of the table quickly in Oracle
Promise (III)
Generating access keys using JSON webtoken
[C#] 彻底搞明白深拷贝
VsCode-Go
【WPF绑定3】 ListView基础绑定和数据模板绑定
ASP. Net core configuration options (Part 2)
JS failed to change all variables and changed to the return method. Finally, the problem was solved
_ Mold_ Board_
JSON deserialize anonymous array / object
1-2 characteristics of nodejs
C dapper basically uses addition, deletion, modification and query transactions, etc
Abnormal resolution of Xiaomi camera
freeCodeCamp----shape_ Calculator exercise
Your brain expands and shrinks over time — these charts show how
XTask与Kotlin Coroutine的使用对比
Simulation of infrared wireless communication based on 51 single chip microcomputer
Clickhouse SQL operation
Metaprogramming, proxy and reflection