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
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!