D'un autre fil qui m'a donné les informations sur la façon d'ajouter la surveillance à un serveur SQL ...Surveillance SQL et Interjection
See SQL From EntityFramework with Collection-like Queries
Cela fonctionne bien, mais je veux prendre un peu plus loin. J'aimerais pouvoir ajouter des commentaires dans le journal lorsque des transactions sont en cours.
Je veux être capable d'écrire des commentaires dans les choses, mais, qui va entrer dans l'enregistrement SQL. Donc, comme je peux faire une requête, et appelez Debugger.Logger.Write ("Une sorte de commentaire"), donc je sais ce que c'est. Je ne connais pas très bien le SQL, alors j'essaie de comprendre ce qui se passe et où.
Toute aide est grandement appréciée. Je suppose que je devrais exécuter une autre requête SQL pour 'insérer' le commentaire dans le flux de la requête.
Je conçois mon contexte de données (DbContext)
using(var context = new SampleDataContext(dbModel))
{
// ...
// prepare a logging model.
if (Debugger.SetupLog(context))
Console.WriteLine("Logging Enabled...");
// open up the debugger log
Debugger.Open();
}
public class SampleDataContext: DbContext, IDisposable
{
public new void Dispose()
{
Debugger.Log(this);
base.Dispose();
}
}
Puis la classe Debugger ..
public static class Debugger
{
public static System.IO.TextWriter File
{
get;
set;
}
public static void Open()
{
// open a file for storing SQL results from queries
File = new System.IO.StreamWriter("results.sql", false);
}
public static void Write(string text)
{
File.WriteLine(text);
}
public static bool Log(SampleDataContext context)
{
var results = context.Database.Connection.CreateCommand();
results.CommandText = Sql.Review;
context.Database.Connection.Open();
System.Data.Common.DbDataReader resultsReader;
do
{
resultsReader = results.ExecuteReader();
}
while (resultsReader == null);
Console.WriteLine("Discovered a Data Reader");
// Retrieves the schema of the table.
var dtSchema = resultsReader.GetSchemaTable();
string strRow; // represents a full row
// Reads the rows one by one from the SqlDataReader
// transfers them to a string with the given separator character and
// writes it to the file.
while (resultsReader.Read())
{
Console.WriteLine("Reading Data Reader... ");
strRow = "";
for (int i = 0; i < resultsReader.FieldCount; i++)
{
strRow += resultsReader.GetValue(i).ToString();
if (i < resultsReader.FieldCount - 1)
{
strRow += " ";
}
}
Sql.Text.Lexer lexer = new Sql.Text.Lexer();
lexer.Enscribe();
var matches = lexer.Tokenize(strRow);
matches.ForEach(x =>
{
strRow = strRow.Replace(x.Value, Environment.NewLine);
});
File.WriteLine(strRow);
}
File.Close();
context.Database.Connection.Close();
return false;
}
public static bool SetupLog(SampleDataContext context)
{
var command = context.Database.Connection.CreateCommand();
command.CommandText = Sql.Record;
context.Database.Connection.Open();
command.ExecuteNonQuery();
context.Database.Connection.Close();
return true;
}
}
J'ai essentiellement inséré l'instruction SQL suivante dans une ressource en C# ...
Ceci est "Project.SQL.Record".
IF EXISTS(SELECT * FROM sys.server_event_sessions WHERE name='test_trace')
DROP EVENT SESSION [test_trace] ON SERVER;
CREATE EVENT SESSION [test_trace]
ON SERVER
ADD EVENT sqlserver.sp_statement_completed(
ACTION (package0.callstack, sqlserver.session_id, sqlserver.sql_text)
-- WHERE (([sqlserver].[username]='Domain\Username'))
),
ADD EVENT sqlserver.sql_statement_completed(
ACTION (package0.callstack, sqlserver.session_id, sqlserver.sql_text)
--WHERE (([sqlserver].[username]='Domain\Username'))
)
ADD TARGET package0.ring_buffer
WITH (MAX_MEMORY = 4096KB, EVENT_RETENTION_MODE = ALLOW_SINGLE_EVENT_LOSS,
MAX_DISPATCH_LATENCY = 1 SECONDS, MAX_EVENT_SIZE = 0KB,
MEMORY_PARTITION_MODE = NONE, TRACK_CAUSALITY = OFF, STARTUP_STATE = OFF)
ALTER EVENT SESSION [test_trace] ON SERVER STATE = START
Puis j'ai un autre, "Project.SQL.Review".
DECLARE
@session_name VARCHAR(200) = 'test_trace'
SELECT
pivoted_data.*
FROM
(
SELECT MIN(event_name) AS event_name,
MIN(event_timestamp) AS event_timestamp,
unique_event_id,
CONVERT (BIGINT, MIN (
CASE
WHEN d_name = 'cpu'
AND d_package IS NULL
THEN d_value
END)) AS [cpu],
CONVERT (BIGINT, MIN (
CASE
WHEN d_name = 'duration'
AND d_package IS NULL
THEN d_value
END)) AS [duration],
CONVERT (BIGINT, MIN (
CASE
WHEN d_name = 'object_id'
AND d_package IS NULL
THEN d_value
END)) AS [object_id],
CONVERT (INT, MIN (
CASE
WHEN d_name = 'object_type'
AND d_package IS NULL
THEN d_value
END)) AS [object_type],
CONVERT (DECIMAL(28,0), MIN (
CASE
WHEN d_name = 'reads'
AND d_package IS NULL
THEN d_value
END)) AS [reads],
CONVERT (VARCHAR(MAX), MIN (
CASE
WHEN d_name = 'session_id'
AND d_package IS NOT NULL
THEN d_value
END)) AS [session_id],
CONVERT (INT, MIN (
CASE
WHEN d_name = 'source_database_id'
AND d_package IS NULL
THEN d_value
END)) AS [source_database_id],
CAST((SELECT CONVERT (VARCHAR(MAX), MIN (
CASE
WHEN d_name = 'sql_text'
AND d_package IS NOT NULL
THEN d_value
END)) AS [processing-instruction(x)] FOR XML PATH('')) AS XML) AS [sql_text],
CONVERT (DECIMAL(28,0), MIN (
CASE
WHEN d_name = 'writes'
AND d_package IS NULL
THEN d_value
END)) AS [writes]
FROM
(
SELECT
*,
CONVERT(VARCHAR(400), NULL) AS attach_activity_id
FROM
(
SELECT
event.value('(@name)[1]', 'VARCHAR(400)') as event_name,
event.value('(@timestamp)[1]', 'DATETIME') as event_timestamp,
DENSE_RANK() OVER (ORDER BY event) AS unique_event_id,
n.value('(@name)[1]', 'VARCHAR(400)') AS d_name,
n.value('(@package)[1]', 'VARCHAR(400)') AS d_package,
n.value('((value)[1]/text())[1]', 'VARCHAR(MAX)') AS d_value,
n.value('((text)[1]/text())[1]', 'VARCHAR(MAX)') AS d_text
FROM
(
SELECT
(
SELECT
CONVERT(xml, target_data)
FROM sys.dm_xe_session_targets st
JOIN sys.dm_xe_sessions s ON
s.address = st.event_session_address
WHERE
s.name = @session_name
AND st.target_name = 'ring_buffer'
) AS [x]
FOR XML PATH(''), TYPE
) AS the_xml(x)
CROSS APPLY x.nodes('//event') e (event)
CROSS APPLY event.nodes('*') AS q (n)
) AS data_data
) AS activity_data
GROUP BY
unique_event_id
) AS pivoted_data;
Ma première pensée était de faire une méthode comme celui-ci ..
public static void WriteSql(SampleDataContext context, string text)
{
var command = context.Database.Connection.CreateCommand();
command.Parameters.Add(new System.Data.SqlClient.SqlParameter("@Comment",System.Data.SqlDbType.VarChar));
command.Parameters["@Comment"].Value = String.Format("--{0}", text);
command.CommandText = String.Format("PRINT '{0}'", text.Replace("'", "''"));
context.Database.Connection.Open();
command.ExecuteNonQuery();
context.Database.Connection.Close();
}
Il devrait exécuter le commentaire comme une requête, qui devrait apparaître dans l'examen, non? Eh bien, ça n'a pas marché. Donc je suis ouvert à d'autres idées ...
J'ai modifié le dernier morceau de mon code pour refléter votre suggestion, mais tout ce qu'il montre est le SQL brut « PRINT @Comment » dans la sortie. Des idées où je me trompe? – Ciel
Non. Essayez peut-être d'utiliser 'varchar' plutôt que du texte comme paramètre. 'text' est un type de données LOB donc peut ne pas fonctionner avec print. Si cela ne je suppose que vous pouvez simplement utiliser fonctionne pas alors quelque chose comme 'Command.CommandText = String.Format (« IMPRIMER « {0} » », text.Replace (« ' », « « » »));' comme c'est votre code qui crée les commentaires et vous n'avez pas à vous soucier de l'injection SQL. –
J'ai mis à jour mon code ci-dessus dans la méthode WriteSql et toujours aucun dé. Il ne montre rien dans la sortie Sql. – Ciel