How to log custom metadata/context info with each query - sql-server

I'm making extensive use of Entity Framework, and I need to optimize a lot of DB work.
I see many inefficient queries running in sys.dm_exec_sessions etc, but the problem is I don't have much context as to which code is initiating this query.
is there a way in EF to add some 'context' to each query, which can be viewed in the sys.dm_ queries?
pseudo-code:
dim d=mydbcontext
d.ContextInfo="Report Window 99"'???
dim results=d.set(of client).ToList
And then when I view SQL Servers log, I'll see next to each query the 'ContextInfo' that I set.
I see that SQL Server has a field context_info, but I haven't manage to see it in sys.dm_exec_sessions, also I have no idea how to set it via EF (and its limited to numeric values)
Thanks so much!

heres a very simple way
Dim csb = New SqlConnectionStringBuilder(cs)
csb.ApplicationName = "all my logging info..."

Related

MS Access/OleDB: No value given for one or more required parameter <- How to debug?

This has to be by far the worst error message I've ever seen in any context. Coming from SQL Server and now revamping a legacy Access database, this error just keeps coming again and again and it's a complete trial and error every time, being a huge time waster.
Any helpful tips on how to debug this error effectively? Like giving even the slightest hint on where to look? I'm using C#.
Well, if using say sql server, one would fire up SQL studio, and try the sql that way.
And the same approach works for Access. Take your sql (debug.print it out), and then cut + paste the sql into the access query builder (in sql view mode). If you run the query, then for any missing field, it will spit out a prompt with the "name" of the column.
Access uses (when from Access) a prompt system for any column that is not in the table, and automatic prompts the user for the value. If you use odbc, or oleDB, then missing columns spit out that missing parameter (but without the name of the column as you note).
So, most easy is to fire up access and use the sql view in the query builder - paste in your sql.
You can use ADO to create the query, and then list all parameters the query expects:
ADODB.Connection conn = new ADODB.Connection();
conn.Open("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Path\\To\\db.accdb");
ADODB.Command cmd = new ADODB.Command
{
CommandText = "SELECT * FROM tblUsers WHERE username = bob",
//Oops, forgot to quote the username, results in No value given for parameter error
ActiveConnection = conn
};
foreach(ADODB.Parameter param in cmd.Parameters)
{
Console.WriteLine(param.Name); //bob
}
Console.ReadLine();
This requires a reference to ADO, which can be entered through the COM references.
You could also use late binding to prevent the extra reference, which might be desirable if you only use this as debug code but want it in your project, see this Q&A.
Since OLEDB doesn't support named parameters, you unfortunately can't use OLEDB for this afaik.
Of course, you can rewrite this to a function that takes a query string and returns expected parameters as a string, and then use that function in the immediate window when debugging.

Is there any way to "name" or "tag" a LINQ query so that it can be identified by a tool like Ignite SQL easier?

Our team is moving towards LINQ, but one of the problems we've run up against is that you cannot easily identify where a LINQ query is coming from using tools like Ignite SQL.
Previously we have been using Stored Procedures, which are easy to track with Ignite. Find a problem Query, find the Stored Procedure that uses it, find the code that calls that Stored Procedure.
With LINQ, when a trouble Query shows up...we have no way to identify what is actually executing that code.
We are looking for a way to "tag" or "name" a LINQ query, so that we can better track our trouble queries back to code.
No, there is no way to do this. I would require a special command on top of the already leaky abstraction of IQueryable that EF implements. Something like db.Entities.Select(...).Name("Query1"). There are two alternatives (that I can think of).
By far the best option is to look at the query closely and try to reason it back to to point in the application it comes from. Why is this the best option? Because by doing this you gain insight in the kind of queries EF generates from which kind of LINQ statements. Soon you'll see a query and think ah, this must be a GroupBy, that must be an Any, etc. Together with the table and column names it should be possible to find the culprit.
The typical software developer's option, so inherently lazy and by definition not the best one: create a command interceptor that executes a special SELECT after EF's SQL commands.
using System.Data.Entity.Infrastructure.Interception;
...
public class StackTraceCommandInterceptor : DbCommandInterceptor
{
public override void ReaderExecuted(
DbCommand command,
DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
if (command.CommandText.StartsWith("SELECT"))
{
var cmd = command.Connection.CreateCommand();
cmd.CommandText = string.Format("SELECT '{0}'",
new System.Diagnostics.StackFrame(17));
cmd.ExecuteNonQuery();
}
}
}
And somewhere in your application startup:
DbInterception.Add(new StackTraceCommandInterceptor());
As you can see, after each SELECT command a new command is composed that SELECTs a text from nothing, so the only thing it does is make itself visible in any database profiling tool (it is not logged by EF's own logging, by the way). The text it logs is the 18th stack frame. From a bit of trial and error with EF's the current source this appeared to contain the method that executed the LINQ statement. Maybe with other versions it is different. If necessary you can output new System.Diagnostics.StackStrace(), i.e. the whole stack trace.
Needless to say that this interceptor should only be activated for diagnostic purposes.

How to solve this in Access forms with Visual basic SQL server connection?

I created a form that essentially show me the Orders from the familiar Northwind database, I´m using Microsoft SQL Server 2008, Microsoft Access 2007 with Visual basic (ADO), so I created the basic form, which pretty much looks like this:
http://www.flickr.com/photos/63259070#N06/7014481001/in/photostream/
Granted it is in Spanish and I'm terrible sorry but hopefully that wont hamper your ability to help me out, So as you can see there is a big main form and then there is a little form consisting of four text bars which of course are attributes or columns in a database called order details So as you can see from this relation:
flickr.com/photos/63259070#N06/6868373952/in/photostream/
You have the table orders (Pedido) and the table order details (Detalle de pedidos), what I want to do is when I click the main >>, the products show accordingly to the Orders, hopefully this will make sense when im on a order and click the sub form with the four elements, it should only show me the products, price, quantity, product id, according to the Order ID in the main form when I click the >> or << in the sub form....
So to exemplify say I have an order ID of 001 and 001 ordered three products, salt, pepper, chicken ... it should only show me that in the sub form.. Hopefully you got this I hope.. please
Here is my complete VB 6 code... again any help is well appreciated thanks...
https://docs.google.com/document/d/1bn71VqxzB1W55sHcKMstCSxnIbmP5cyYWkBVnF1tzVs/edit
I've experimented a great deal with ADO in Access and I finally concluded that it is not the best technology to use when it comes forms and reports in MS Access. It's OK for connecting to data sources that can only be access through ADO, or in which there is a significant advantage to using ADO (such as speed) but in those cases you must make compromises which often require you to omit certain features or work very hard to code them. Comboboxes that use a SQL statement (as opposed to a Value List) are difficult to setup and will require you to load a separate recordset in order to fill them with options. I've found sorting to not always work properly and reliably, specifically in datasheet view forms. In short, it's a lot more work and code to make ADO work in Access forms unless you keep your forms exceedingly simple (and that often makes them clumsy to use).
What I recommend you do instead is use ODBC linked tables. This might require you to first install a SQL Server ODBC driver. After you have your linked tables setup in Access, you can then use Access as though those tables were local tables. You can use bound forms (which automatically use DAO to access data) and setting up master/detail forms is a breeze under this configuration. You can even use the wizards though I wouldn't necessarily recommend that.
If you do insist on using ADO, I recommend you experiment with setting the form's recordset to the ADO recordset. This would then be a bound form and would keep you from having to write code to move data from the recordset into the controls and vice versa. Here's some of your code modified to do that:
Private Sub Form_Load()
Set con = Nothing
Set rs = Nothing
Set rs2 = Nothing
Set con = New ADODB.Connection
Set rs = New ADODB.Recordset
Set rs2 = New ADODB.Recordset
con.ConnectionString = "Provider=SQLNCLI10.1;User ID=sa0378;password=123;Initial Catalog=Northwind;Data Source=(local);"
con.Open
rs.Open "SELECT Orders.OrderID, Orders.ShipCountry," & _
"Orders.EmployeeID, Orders.CustomerID, Orders.ShipCity," & _
"Orders.ShipAddress, Orders.ShipPostalCode, Orders.Freight, Orders.OrderDate," & _
"Orders.RequiredDate, Orders.ShippedDate FROM Orders", con, _
adOpenDynamic, adLockOptimistic
Set Me.Recordset = rs
End Sub
That code however won't setup the master/detail relationship your looking for. It will still be your job to make that happen manually by loading the correct recordset anytime the user changes to a different record on the main form. You should be able to do this on the form's Current event.

executing insert\update\deletes - Use Linq?

I was looking at using linq to sql (or EF) rather than in line\dynamic sql within my application but have hit a possible issue. My application modifies data against any number of random databases accross several sql instances, linq appears to structured towards a single database scenario. Would it be best to just continue using in line sql or is there a method of using linq without tying it down to a single database?
An example of what I'm doing at the moment:
Using cn As SqlConnection = (ConnectionString)
Using cm As SqlCommand = New SqlCommand("< Dynamic sql>;", cn)
cn.Open()
cn.ChangeDatabase(Database)
cm.ExecuteNonQuery()
End Using
End Using
And example of a query would be:
DELETE FROM settings WHERE [Sec] = 'ON' AND [Key] = 'last'; INSERT Settings([Sec], [Key], [Val]) values('ON', 'last', GETDATE());
Although I am executing stored procedures within these databases, some custom, others for adding users (sp_adduser)
All target databases have the same structure, so any query\linq would work against it.
With LINQ, you are correct in that a DataContext goes to one single database, but you can have many DataContexts, each going to a different database. You can have, for example, a SettingsDataContext going to the database with your settings and a UsersDataContext going to the database with your users, or however you have it set up.
There is the syntax of it all. Here is a link to some examples of doing inserts and selects with ADO.NET and Linq to SQL.
http://blogs.msdn.com/b/wriju/archive/2008/07/14/linq-to-sql-vs-ado-net-a-comparison.aspx
One thing I have heard often is that Linq to SQL is for those that aren't real comfortable with SQL or who just like to work in the realms of C# or VB.NET code more than having to switch thought patterns and think in the ADO.NET/inline SQL realm.

VB6/Microsoft Access/DAO to VB.NET/SQL Server... Got Advice?

I can make a DAO recordset in VB6/Access do anything - add data, clean data, move data, get data dressed in the morning and take it to school. But I don't even know where to start in .NET.
I'm not having any problems retrieving data from the database, but what do real people do when they need to edit data and put it back?
What's the easiest and most direct way to edit, update and append data into related tables in .NET and SQL Server?
The DataSet class is the place to start. As the linked article says, the steps for creating a DataSet, modifying it, then updating the database are typically:
Build and fill each DataTable in a DataSet with data from a data source using a DataAdapter.
Change the data in individual DataTable objects by adding, updating, or deleting DataRow objects.
Invoke the GetChanges method to create a second DataSet that features only the changes to the data.
Call the Update method of the DataAdapter, passing the second DataSet as an argument.
Invoke the Merge method to merge the changes from the second DataSet into the first.
Invoke the AcceptChanges on the DataSet. Alternatively, invoke RejectChanges to cancel the changes.
A natural progression IMO from DAO is ADO.net. I think you would find it pretty easy to pick up having the understanding/foundation of DAO. It uses DataAdapters and DataSets similar to recordsets. Modifying Data in ADO.NET.
I would suggest looking into Linq when you get a chance.
Is there a reason why ms-access was added as a tag here? It seems to me that the question has nothing but the most trivial relevance to Access, since once you're working with .NET, Access is completely out of the picture.
try to use oledbConnection , oledbCommand and oledbDataReader
from System.data.oledb
if you are using sqlserver DB, then use SqlConnection , sqlCommand and sqlDataReader
from System.data.SqlClient

Resources