当前位置:首页 > 行业动态 > 正文

c# 数据库更改记录

csharp,using System;,using System.Data;,using System.Data.SqlClient;class Program,{, static void Main(), {, string connectionString = "Your_Connection_String";, string query = "UPDATE YourTable SET Column1 = 'NewValue' WHERE Condition"; using (SqlConnection connection = new SqlConnection(connectionString)), {, SqlCommand command = new SqlCommand(query, connection);, try, {, connection.Open();, int rowsAffected = command.ExecuteNonQuery();, Console.WriteLine($"Rows affected: {rowsAffected}");, }, catch (Exception ex), {, Console.WriteLine($"Error: {ex.Message}");, }, }, },},

在C#中,记录数据库更改是一项常见且重要的任务,它有助于跟踪数据的变更历史,进行审计和数据恢复等操作,以下是关于如何在C#中实现数据库更改记录的详细内容:

一、使用数据库触发器

1、创建触发器

概念:触发器是一种特殊的存储过程,它在插入、更新或删除表中的数据时自动执行,通过在相关的数据库表上创建触发器,可以在数据发生更改时自动记录相关信息。

示例代码

假设有一个名为Orders的表,包含订单信息,当订单信息发生更新时,我们希望记录下更改的详细信息,可以创建一个名为Orders_Update_Trigger的触发器:

“`sql

CREATE TRIGGER Orders_Update_Trigger

ON Orders

FOR UPDATE

AS

BEGIN

INSERT INTO OrderChanges (OrderID, OldValue, NewValue, ChangeDate)

SELECT INSERTED.OrderID, DELETED.ColumnName, INSERTED.ColumnName, GETDATE()

FROM INSERTED

JOIN DELETED ON INSERTED.OrderID = DELETED.OrderID

END

     在这个触发器中,当Orders表的数据被更新时,会自动将旧值和新值插入到OrderChanges表中,同时记录更改的时间。INSERTED表示更新后的数据,DELETED表示更新前的数据。
2、**在C#中调用触发器**
   在C#应用程序中,不需要额外的代码来手动调用触发器,只需要按照正常的数据库操作流程对数据进行修改即可,当数据修改语句执行时,触发器会自动触发并记录更改。
二、使用C#代码记录更改
1、在数据访问层记录更改概念:在与数据库交互的数据访问层(DAL)中,可以在执行数据更新操作前后添加代码来记录更改信息,这种方法需要手动编写记录逻辑,但可以更灵活地控制记录的内容和格式。示例代码:
     假设使用ADO.NET连接到数据库,以下是一个在更新订单信息时记录更改的示例:
     ```csharp
       using (SqlConnection connection = new SqlConnection(connectionString))
       {
           connection.Open();
           using (SqlCommand command = new SqlCommand("UPDATE Orders SET ColumnName = @NewValue WHERE OrderID = @OrderID", connection))
           {
               command.Parameters.AddWithValue("@OrderID", orderID);
               command.Parameters.AddWithValue("@NewValue", newValue);
               int rowsAffected = command.ExecuteNonQuery();
               if (rowsAffected > 0)
               {
                   // 记录更改信息
                   using (SqlCommand logCommand = new SqlCommand("INSERT INTO OrderChanges (OrderID, OldValue, NewValue, ChangeDate) VALUES (@OrderID, @OldValue, @NewValue, @ChangeDate)", connection))
                   {
                       logCommand.Parameters.AddWithValue("@OrderID", orderID);
                       // 这里需要先查询出旧值
                       string oldValue = GetOldValueFromDatabase(orderID);
                       logCommand.Parameters.AddWithValue("@OldValue", oldValue);
                       logCommand.Parameters.AddWithValue("@NewValue", newValue);
                       logCommand.Parameters.AddWithValue("@ChangeDate", DateTime.Now);
                       logCommand.ExecuteNonQuery();
                   }
               }
           }
       }
       private string GetOldValueFromDatabase(int orderID)
       {
           // 根据业务逻辑从数据库中获取旧值
           // 这里只是一个简单的示例,实际可能需要根据具体的表结构和需求进行查询
           using (SqlConnection connection = new SqlConnection(connectionString))
           {
               connection.Open();
               using (SqlCommand command = new SqlCommand("SELECT ColumnName FROM Orders WHERE OrderID = @OrderID", connection))
               {
                   command.Parameters.AddWithValue("@OrderID", orderID);
                   using (SqlDataReader reader = command.ExecuteReader())
                   {
                       if (reader.Read())
                       {
                           return reader["ColumnName"].ToString();
                       }
                       else
                       {
                           throw new Exception("未找到对应的旧值");
                       }
                   }
               }
           }
       }

在这个示例中,首先执行更新订单信息的SQL命令,然后检查受影响的行数,如果有行被更新,则通过另一个SQL命令将更改信息插入到OrderChanges表中,在插入记录之前,需要先从数据库中查询出旧值。

2、使用ORM框架记录更改

概念:如果使用对象关系映射(ORM)框架,如Entity Framework,可以利用其提供的事件机制来记录数据库更改,在Entity Framework中,可以订阅SavingChanges事件,在该事件中获取即将保存的更改信息并进行记录。

示例代码

“`csharp

public class MyDbContext : DbContext

{

public DbSet<Order> Orders { get; set; }

public DbSet<OrderChange> OrderChanges { get; set; }

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)

{

optionsBuilder.UseSqlServer(connectionString);

c# 数据库更改记录  第1张

base.OnConfiguring(optionsBuilder);

}

protected override void OnModelCreating(ModelBuilder modelBuilder)

{

base.OnModelCreating(modelBuilder);

// 配置模型等

}

}

public class OrderChange

{

public int OrderChangeID { get; set; }

public int OrderID { get; set; }

public string OldValue { get; set; }

public string NewValue { get; set; }

public DateTime ChangeDate { get; set; }

}

public class OrderChangeService

{

private readonly MyDbContext _context;

c# 数据库更改记录  第2张

public OrderChangeService(MyDbContext context)

{

_context = context;

_context.SavingChanges += OnSavingChanges;

}

private void OnSavingChanges(object sender, EventArgs e)

{

foreach (var entry in _context.ChangeTracker.Entries())

{

if (entry.State == EntityState.Modified)

{

// 获取实体的原始值和新值,并记录更改

var originalValues = entry.OriginalValues.ToDictionary(k => k.Key, v => v.CurrentValue);

var currentValues = entry.CurrentValues.ToDictionary(k => k.Key, v => v.CurrentValue);

foreach (var property in originalValues)

{

if (!currentValues.ContainsKey(property.Key) || !currentValues[property.Key].Equals(property.Value))

{

OrderChange change = new OrderChange

c# 数据库更改记录  第3张

{

OrderID = entry.Entity.GetType().GetProperty("OrderID")?.GetValue(entry.Entity) as int,

OldValue = property.Value.ToString(),

NewValue = currentValues[property.Key].ToString(),

ChangeDate = DateTime.Now

};

_context.OrderChanges.Add(change);

}

}

}

}

// 确保更改记录被保存到数据库中

_context.SaveChanges();

}

}

     在这个示例中,创建了一个自定义的MyDbContext类,并订阅了SavingChanges事件,在事件处理程序OnSavingChanges中,遍历所有被修改的实体,获取它们的原始值和新值,并将更改信息保存到OrderChanges表中,调用SaveChanges方法确保更改记录被保存到数据库中。
三、记录更改的信息内容
1、基本信息实体标识:记录被更改的实体的唯一标识符,例如订单号、用户ID等,这有助于确定是哪一条数据发生了更改。更改时间:记录更改发生的具体时间,精确到秒或毫秒级别,这对于追踪数据的变更顺序和时间点非常重要。操作类型:明确指出是插入、更新还是删除操作,不同的操作类型可能需要记录不同的信息。
2、旧值和新值具体字段值:记录被更改字段的名称和对应的旧值和新值,这样可以清晰地看到数据在更改前后的差异,对于复杂的实体,可能需要记录多个字段的更改情况。数据格式:根据数据的类型选择合适的格式来记录值,对于数值型数据可以直接记录数值,对于字符串型数据可以进行适当的截断或编码处理,以防止数据过长。
3、其他相关信息用户名或用户ID:如果是由特定用户发起的更改,记录执行操作的用户信息,这有助于追溯责任和进行安全审计。备注信息:可以添加一些额外的备注来描述更改的原因、背景或其他相关信息,这对于后续的分析和理解可能会有所帮助。
四、存储更改记录的表结构设计
1、表结构示例
   以订单更改记录为例,可以设计一个名为OrderChanges的表来存储更改信息:
   |列名|数据类型|说明|
   |---|---|---|
   |OrderChangeID|int|自增长的主键,唯一标识每一条更改记录|
   |OrderID|int|关联到订单表的外键,表示被更改的订单|
   |OldValue|nvarchar(max)|存储被更改字段的旧值,可以使用JSON或其他格式来存储多个字段的值|
   |NewValue|nvarchar(max)|存储被更改字段的新值|
   |ChangeDate|datetime|记录更改发生的时间|
   |ChangedBy|int|记录执行更改操作的用户ID,关联到用户表的外键|
   |Notes|nvarchar(max)|可选的备注信息,用于描述更改的原因等|
2、索引设计
   根据查询需求,可以为OrderIDChangeDate等列创建索引,以提高查询性能,如果经常需要按照订单ID查询某个订单的所有更改记录,可以为OrderID列创建索引。
五、性能考虑
1、批量处理
   如果有大量的数据更改需要记录,可以考虑批量插入更改记录到数据库中,以减少数据库的开销和提高性能,可以将多个更改记录组织成一个事务进行插入操作。
   ```csharp
     using (SqlConnection connection = new SqlConnection(connectionString))
     {
         connection.Open();
         using (SqlTransaction transaction = connection.BeginTransaction())
         {
             using (SqlCommand batchCommand = new SqlCommand("INSERT INTO OrderChanges (OrderID, OldValue, NewValue, ChangeDate) VALUES (...)", connection))
             batchCommand.Connection.Open();
             for (int i = 0; i < changes.Count; i++)
                 {
                     batchCommand.Parameters.Clear();
                     batchCommand.Parameters.AddWithValue("@OrderID", changes[i].OrderID);
                     batchCommand.Parameters.AddWithValue("@OldValue", changes[i].OldValue);
                     batchCommand.Parameters.AddWithValue("@NewValue", changes[i].NewValue);
                     batchCommand.Parameters.AddWithValue("@ChangeDate", changes[i].ChangeDate);
                     batchCommand.ExecuteNonQuery();
                 }
             transaction.Commit();
         }
     }

2、异步操作

如果记录更改的操作比较耗时,可以考虑使用异步编程来避免阻塞主线程,在ASP.NET Core应用中,可以使用异步方法来处理数据库操作。

0