Logging every data change with Entity Framework

后端 未结 8 1046
醉酒成梦
醉酒成梦 2020-12-02 14:43

There is a need from a customer to log every data change to a logging table with the actual user who made the modification. The application is using one SQL user to access t

8条回答
  •  悲哀的现实
    2020-12-02 15:13

    Finally with Craig's help, here is a proof of concept. It needs more testing, but for first look it is working.

    First: I created two tables, one for data one for logging.

    -- This is for the data
    create table datastuff (
        id int not null identity(1, 1),
        userid nvarchar(64) not null default(''),
        primary key(id)
    )
    go
    
    -- This is for the log
    create table naplo (
        id int not null identity(1, 1),
        userid nvarchar(64) not null default(''),
        datum datetime not null default('2099-12-31'),
        primary key(id)
    )
    go
    

    Second: create a trigger for insert.

    create trigger myTrigger on datastuff for insert as
    
        declare @User_id int,
            @User_context varbinary(128),
            @User_id_temp varchar(64)
    
        select @User_context = context_info
            from master.dbo.sysprocesses
            where spid=@@spid
    
        set @User_id_temp = cast(@User_context as varchar(64))
    
        declare @insuserid nvarchar(64)
    
        select @insuserid=userid from inserted
    
        insert into naplo(userid, datum)
            values(@User_id_temp, getdate())
    
    go
    

    You should also create a trigger for update, which will be a little bit more sophisticated, because it needs to check every field for changed content.

    The log table and the trigger should be extended to store the table and field which is created/changed, but I hope you got the idea.

    Third: create a stored procedure which fills in the user id to the SQL context info.

    create procedure userinit(@userid varchar(64))
    as
    begin
        declare @m binary(128)
        set @m = cast(@userid as binary(128))
        set context_info @m
    end
    go
    

    We are ready with the SQL side. Here comes the C# part.

    Create a project and add an EDM to the project. The EDM should contain the datastuff table (or the tables you need to watch for changes) and the SP.

    Now do something with the entity object (for example add a new datastuff object) and hook to the SavingChanges event.

    using (testEntities te = new testEntities())
    {
        // Hook to the event
        te.SavingChanges += new EventHandler(te_SavingChanges);
    
        // This is important, because the context info is set inside a connection
        te.Connection.Open();
    
        // Add a new datastuff
        datastuff ds = new datastuff();
    
        // This is coming from a text box of my test form
        ds.userid = textBox1.Text;
        te.AddTodatastuff(ds);
    
        // Save the changes
        te.SaveChanges(true);
    
        // This is not needed, only to make sure
        te.Connection.Close();
    }
    

    Inside the SavingChanges we inject our code to set the context info of the connection.

    // Take my entity
    testEntities te = (testEntities)sender;
    
    // Get it's connection
    EntityConnection dc = (EntityConnection )te.Connection;
    
    // This is important!
    DbConnection storeConnection = dc.StoreConnection;
    
    // Create our command, which will call the userinit SP
    DbCommand command = storeConnection.CreateCommand();
    command.CommandText = "userinit";
    command.CommandType = CommandType.StoredProcedure;
    
    // Put the user id as the parameter
    command.Parameters.Add(new SqlParameter("userid", textBox1.Text));
    
    // Execute the command
    command.ExecuteNonQuery();
    

    So before saving the changes, we open the object's connection, inject our code (don't close the connection in this part!) and save our changes.

    And don't forget! This needs to be extended for your logging needs, and needs to be well tested, because this show only the possibility!

提交回复
热议问题