Skip to content

Instantly share code, notes, and snippets.

@ghuntley
Forked from NickCraver/ExampleUsage.cs
Created August 18, 2016 23:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ghuntley/aa5a92d020035e8ee0a71e0b20465d5c to your computer and use it in GitHub Desktop.
Save ghuntley/aa5a92d020035e8ee0a71e0b20465d5c to your computer and use it in GitHub Desktop.
Code to mark a SQL string before it's passed to Dapper.
public static List<T> Query<T>(this DataContext db, string sql, object param = null, int? commandTimeout = null, IDbTransaction transaction = null, [CallerFilePath]string fromFile = null, [CallerLineNumber]int onLine = 0, string comment = null)
{
using (db.Connection.EnsureOpen())
{
try
{
return db.Connection.Query<T>(MarkSqlString(sql, fromFile, onLine, comment), param, transaction ?? db.Transaction, true, commandTimeout).AsDapperList();
}
catch (SqlException ex) when (ex.Is(SqlErrorCode.DatabaseReadOnly_3906))
{
HandleReadOnlyException(db, ex);
return EmptyDapperList<T>();
}
}
}
private static readonly ConcurrentDictionary<int, string> MarkedSql = new ConcurrentDictionary<int, string>();
/// <summary>
/// Takes a SQL query, and inserts the path and line in as a comment.
/// </summary>
private static string MarkSqlString(string sql, string path, int lineNumber, string comment)
{
if (path.IsNullOrEmpty() || lineNumber == 0) return sql;
int key = 17;
unchecked
{
key = key*23 + sql.GetHashCode();
key = key*23 + path.GetHashCode();
key = key*23 + lineNumber.GetHashCode();
if (comment.HasValue()) key = key*23 + comment.GetHashCode();
}
// Have we seen this before???
string output;
if (MarkedSql.TryGetValue(key, out output)) return output;
// nope
var commentWrap = " ";
var i = sql.IndexOf(Environment.NewLine);
// if we didn't find \n, or it was the very end, go to the first space method
if (i < 0 || i == sql.Length - 1)
{
i = sql.IndexOf(' ');
commentWrap = Environment.NewLine;
}
if (i < 0) return sql;
// Grab one directory and the file name worth of the path
// this dodges problems with the build server using temp dirs
// but also gives us enough info to uniquely identify a queries location
var split = path.LastIndexOf('\\') - 1;
if (split < 0) return sql;
split = path.LastIndexOf('\\', split);
if (split < 0) return sql;
split++; // just for Craver
var sqlComment = " /* " + path.Substring(split) + "@" + lineNumber.ToString() + (comment.HasValue() ? " - " + comment : "") + " */" + commentWrap;
var ret = sql.Substring(0, i) + sqlComment + sql.Substring(i);
// Cache, don't allocate all this pass again
MarkedSql[key] = ret;
return ret;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment