当前位置:网站首页>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
边栏推荐
- 【WPF绑定3】 ListView基础绑定和数据模板绑定
- Go language, array, string, slice
- How does matlab draw the curve of known formula and how does excel draw the function curve image?
- Manually implement call, apply and bind functions
- Indexes and views in MySQL
- Shell script -- shell programming specification and variables
- Understanding and small examples of unity3d object pool
- Oninput one function to control multiple oninputs (take the contents of this input box as parameters) [very practical, very practical]
- How to sort the numbers with text in Excel from small to large instead of the first number
- Further study of data visualization
猜你喜欢
Using quartz under. Net core -- job attributes and exceptions of [4] jobs and triggers
Get the column name list of the table quickly in Oracle
C# Task. Delay and thread The difference between sleep
JS, entries(), keys(), values(), some(), object Assign() traversal array usage
Milvus 2.0 détails du système d'assurance de la qualité
On lambda powertools typescript
Milvus 2.0 質量保障系統詳解
Use of five routing guards
01-初识sketch-sketch优势
线性代数感悟之1
随机推荐
Change Oracle to MySQL
[problem solving] [show2012] random tree
Self use learning notes - connected and non connected access to database
Handwritten event publish subscribe framework
Understanding of RPC core concepts
Net standard
How to use the input table one-way service to send (occupy less) picture files (body transmission)? FileReader built-in object involved
Shell - introduction, variables, and basic syntax
Detailed explanation of Milvus 2.0 quality assurance system
Model problems of stock in and stock out and inventory system
JS to find the character that appears three times in the string
Milvus 2.0 质量保障系统详解
Using quartz under. Net core -- a simple trigger of [7] operation and trigger
[logical fallacy in life] Scarecrow fallacy and inability to refute are not proof
Paging SQL
Shell-awk命令的使用
Customize my_ Strcpy and library strcpy [analog implementation of string related functions]
Use of Shell sort command
freeCodeCamp----prob_ Calculator exercise
Some problems encountered in recent programming 2021 / 9 / 8