Is there a way to identify what method in C# code is connecting and executing a query?
My thoughts so far is to generate a unique user for each connection in the application and then examine the SQL Server system tables to view the original_login_user.
I should note that I am using Azure SQL.
The OP is using Entity Framework, and you can log all SQL Queries that EF performs by doing something like
using (var context = new BlogContext())
{
context.Database.Log = Console.Write;
// your code here...
}
See the following for more information: https://msdn.microsoft.com/en-us/library/dn469464(v=vs.113).aspx
Related
I am designing a testing framework that makes extensive use of SQL Sever Database. I am using Entity Framework 6 of .NET to felicitate it. I want to log the Underlying SQL query each time when I run a test case. I am using LINQ to SQL for querying Database.
I am having a hard time logging the SQL. LINQ to SQL generates some uncooked SQL which needs to be converted into SQL by filling in the parameters which I want to avoid.
Is there a better approach which will log all the SQL which I can directly feed to my SQL Server without doing any changes in Query ?
According to Entity Framework Logging:
The DbContext.Database.Log property can be set to a delegate for any method that takes a string. Most commonly it is used with any TextWriter by setting it to the “Write” method of that TextWriter. All SQL generated by the current context will be logged to that writer. For example, the following code will log SQL to the console:
using (var context = new BlogContext())
{
context.Database.Log = Console.Write;
// Your code here...
}
in the above way you should be able to log everything.
The following gets logged:
When the Log property is set all of the following will be logged:
SQL for all different kinds of commands. For example:
Queries, including normal LINQ queries, eSQL queries, and raw queries from methods such as SqlQuery
Inserts, updates, and deletes generated as part of SaveChanges
Relationship loading queries such as those generated by lazy loading
Parameters
Whether or not the command is being executed asynchronously
A timestamp indicating when the command started executing
Whether or not the command completed successfully, failed by throwing an exception, or, for async, was canceled
Some indication of the result value
The approximate amount of time it took to execute the command. Note that this is the time from sending the command to getting the
result object back. It does not include time to read the results.
Looking at the example output above, each of the four commands logged
are:
The query resulting from the call to context.Blogs.First
Notice that the ToString method of getting the SQL would not have worked for this query since “First” does not provide an
IQueryable on which ToString could be called
The query resulting from the lazy-loading of blog.Posts
Notice the parameter details for the key value for which lazy loading is happening
Only properties of the parameter that are set to non-default values are logged. For example, the Size property is only shown if it
is non-zero.
Two commands resulting from SaveChangesAsync; one for the update to change a post title, the other for an insert to add a new post
Notice the parameter details for the FK and Title properties
Notice that these commands are being executed asynchronously
I'm having a bit of a mess around at the moment trying to build a console app where I can insert some data into my database and output the sql to a file as an extra. The idea being is that I could use these for data migrations or something similar.
I have several lookup tables that I'd like to pre-populate with data and I think this is nicer than writing out the sql by hand. If someone needs to look up a value it'll be right there in the code.
I'm using EF Tracing and what I've got so far allows me to log the sql entity framework creates by doing the following
I've hooked into their action to get access to the tracing
private void WriteSqlToString(CommandExecutionEventArgs args)
{
sqlTrace.Append(args.ToTraceString());
}
Which gives something like this
insert [dbo].[Members]([EmailAddress], [FirstName], [LastName])
values (#0, #1, #2)
select [Id]
from [dbo].[Members]
where ##ROWCOUNT > 0 and [Id] = scope_identity()
-- #0 (dbtype=String, size=60, direction=Input) = "email#email.com"
-- #1 (dbtype=String, size=-1, direction=Input) = "TestFirstName"
-- #2 (dbtype=String, size=-1, direction=Input) = "TestLastName"
I'll be the first to hold my hand up because I'm not good at writing sql by hand. I've messed about with this a little to try and get it to execute in sqlserver express but keep getting errors because the variables aren't declared.
Do folk think it's worth continuing trying to get this to work or am I missing a better solution here?
Here's some more of the code for reference
public void CreateSqlFile()
{
using (MyContext context = tracingContextFactory.Create(WriteSqlToString))
{
Migrate(context);
context.SaveChanges();
}
StreamWriter file = new StreamWriter(migrationPath);
file.WriteLine(sqlTrace.ToString());
file.Close();
}
The SQL generated from EF is functional, but it is normally overly complex and badly formatted.
Which is fine, for EF, because no-one ever sees the SQL.
However, if you're going to use or try to modify the SQL, I'd go for a different route. If you're trying to do data migrations, for example, I'd look at SQL Server Integration Services (SSIS).
Edit
To generate data to transfer between servers, in SQL Server management studio,
Right click on the database,
Click generate scripts.
Select your table.
On the next screen, choose Advanced Options
In "types of data to script", choose "Data only". (or Schema and Data, as appropriate)
Continue to the end of the wizard
Success.
I would like for it to use SQL Server by default for everything when I start a new ASP.NET MVC 4 Web Application project. By default when you run this project it creates a LocalDb instance and creates the following tables in it:
webpages_Membership
webpages_OAuthMembership
webpages_Roles
webpages_UsersInRoles
UserProfile
I have been able to use a code first migration to put the UserProfile table into a SQL server database. However, I have not been able to accomplish this with the other 4 tables.
Obviously my goal is to start with a single SQL Server database and have all of the tables for the application contained within the single database.
Open your InitializeSimpleMembershipAttribute.cs file, this is where the WebSecurity database initialization is. You need to modify it with the correct connectionStringName. Example:
Change
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
to
WebSecurity.InitializeDatabaseConnection("MyRealDBConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
IF you want to copy the structure of the web security tables to use with Code First, there is an article .... which I cannot find at the moment ... give me a few.
Well I could not find it - but honestly - it was a pain. The easiest way, since you have the DB generated already, might be to use an Code First reverse engineer tool like Entity Framework Power Tools. This will do most of the work for you. Then just add the classes to your DbContext, create a migration, and update your real database.
Also - you may need to make more modifications than this - depending on your Context name and such.
If your goal is to only create those tables in your existing db, you should perform 2 steps.
First, change the connection string of db initialization as what #Jack said.
Second, in your DbContext, change the constructor like this:
public class MyDbContext : DbContext
{
publicMytDbContext()
: base("MyRealDBConnection")
{
}
// ...
}
I'd like to "dry-run" Hibernate HQL queries. That is I'd like to know what actual SQL queries Hibernate will execute from given HQL query without actually executing the HQL query against real database.
I have access to hibernate mapping for tables, the HQL query string, the dialect for my database. I have also access to database if that is needed.
Now, how can I find out all the SQL queries Hibernate can generate from my HQL without actually executing the query against any database? Are there any tools for this?
Note, that many SQL queries can be generated from one HQL query and the set of generated SQL queries may differ based on the contents of database.
I am not asking how to log SQL queries while HQL query is executing.
Edit: I don't mind connecting to database to fetch some metadata, I just don't want to execute queries.
Edit: I also know what limits and offsets are applied to query. I also have the actual parameters that will be bind to query.
The short answer is "you can't". The long answer is below.
There are two approaches you can take:
A) Look into HQLQueryPlan class, particularly its getSqlStrings() method. It will not get you the exact SQL because further preprocessing is involved before query is actually executed (parameters are bound, limit / offset are applied, etc...) but it may be close enough to what you want.
The thing to keep in mind here is that you'll need an actual SessionFactory instance in order to construct HQLQueryPlan, which means you won't be able to do so without "connecting to any database". You can, however, use in-memory database (SqlLite and the likes) and have Hibernate auto-create necessary schema for it.
B) Start with ASTQueryTranslatorFactory and descend into AST / ANTLR madness. In theory you may be able to hack together a parser that would work without relying on metadata but I have a hardest time imagining what is it you're trying to do for this to be worth it. Perhaps you can clarify? There has to be a better approach.
Update: for an offline, dry-run of some HQL, using HQLQueryPlan directly is a good approach. If you want to intercept every query in the app, while it's running, and record the SQL, you'll have to use proxies and reflection as described below.
Take a look at this answer for Criteria Queries.
For HQL, it's the same concept - you have to cast to Hibernate implementation classes and/or access private members, so it's not a supported method, but it will work with a the 3.2-3.3 versions of Hibernate. Here is the code to access the query from HQL (query is the object returned by session.createQuery(hql_string):
Field f = AbstractQueryImpl.class.getDeclaredField("session");
f.setAccessible(true);
SessionImpl sessionImpl = (SessionImpl) f.get(query);
Method m = AbstractSessionImpl.class.getDeclaredMethod("getHQLQueryPlan", new Class[] { String.class, boolean.class });
m.setAccessible(true);
HQLQueryPlan plan = (HQLQueryPlan) m.invoke(sessionImpl, new Object[] { query.getQueryString(), Boolean.FALSE });
for (int i = 0; i < plan.getSqlStrings().length; ++i) {
sql += plan.getSqlStrings()[i];
}
I would wrap all of that in a try/catch so you can go on with the query if the logging doesn't work.
It's possible to proxy your session and then proxy your queries so that you can log the sql and the parameters of every query (hql, sql, criteria) before it runs, without the code that builds the query having to do anything (as long as the initial session is retrieved from code you control).
I get a Antlr.Runtime.NoViableAltException thrown when trying to run the following query in NHibernate.
IQuery query = session.CreateQuery("from <table> where 1 in (select <column>.STIntersects(geography::STGeomFromText('POINT(:longitude :latitude)', 4326)))");
I'm setting longitude and latitude in setQuery.
my assumption is the :: in calling geography::STGeomFromText... because it's thinking it's a query parameter. Is there a way to escape the :?
This query works in my SQL Manager Studio.
Thanks!
Does NHIbernate support the STIntersects method ?
What you could do, is let NHibernate execute a (native) SQL query, like this:
ISQLQuery query = session.CreateSQLQuery ("your sql statement goes here");
query.AddEntity (typeof(TheEntityTypeThatYouWant));
var result = query.List<TheEntityTypeThatYouWant>();
See this post for some more info: Using SQL Server 2008 Geography types with nHibernate's CreateSQLQuery
Just to share what I ended up doing was taking the ADO connection out of the NHibernate session, performing a SqlCommand directly and manually built my Model objects from the results. It sucks, but it works. The connection still managed by NHibernate correctly.