Visualize generated SQL from Linq To Entities - visual-studio

I am looking for a way to see what the sql is that my L2E code has generated for debugging purposes.
I have read a blogpost by Scott G. on a visualizer for Linq2SQL but I can't get it to work for L2E.
Do you know of some way to visualize the generated SQL from L2E?
I am using Visual Studio 2008 SP1 Professional.

The Class ObjectQuery has a ToTraceString() function. However, most queries that you write in LINQ are created as IQueryable so you first have to cast them to an ObjectQuery in order to use it.
or, if you define this extension method, you can use it with IQ
public static string ToTraceString<T>(this IQueryable<T> expression)
{
ObjectQuery<T> objectQuery = expression as ObjectQuery<T>;
if (objectQuery != null)
{
return objectQuery.ToTraceString();
}
return "";
}
...
//then you could use it like this
IQueryable<Record> records = db.Record.Where(r=>r.Value > x);
string generatedQuery = record.ToTraceString();

Try Sql Server Profile (if you have Sql Server installed).
Open a new Trace window and there you'll see all your queries issued against Sql Server.

Related

Entity Framework Compiled Query

How do I write this Entity Framework LINQ Query as a Compiled Query?
var context = new SlxDbContext();
var userSet = context.Set<User>();
User user = userSet.Where(x => x.UserName == "gstrader").First();
There's no way to use CompiledQuery when you're using the DbContext API; CompiledQuery works only with ObjectContext. If you're using Code First, you're most likely using the DbContext API. And Microsoft recommends that you use the DbContext API in new projects even if you'll be working with Database First or Model First models.
But if you use EF5, it brings auto-compiled queries, which work very differently than CompiledQuery. Instead of your writing code to compile each query and then invoking each as needed, EF5 caches the generated SQL for you as a background process, then searches the cache for already compiled queries when you execute any query.
See:
http://blogs.msdn.com/b/adonet/archive/2012/02/14/sneak-preview-entity-framework-5-0-performance-improvements.aspx
and
http://www.devproconnections.com/article/entity-framework/entity-framework-5-143875
Unfortunately the version of EF you are using (code first), does not support compiled queries.
Please correct me if I'm wrong.
Some links:
How do I precompile an Entity Framework Code-First Query?
EF Code First DbContext and Compiled Queries
http://blogs.msdn.com/b/adonet/archive/2011/03/02/ef-4-1-is-coming-dbcontext-api-amp-code-first-rtw.aspx
UPDATE:
Here is a sample for compiled queries, but I think it's not going to work with Code First:
public static Shop CompiledGetShopById(Guid shopId)
{
using (DataContext dtx = new DataContext(ConfigProvider.ConnectionString)) {
return Compiled_GetById.Invoke(dtx, shopId);
}
}
private static Func<DataContext, Guid, Shop> Compiled_GetById =
Objects.CompiledQuery.Compile<DataContext, Guid, Shop>(
(DataContext db, Guid shopId) =>
(from item in db.Shops where item.ShopId == shopId)
.FirstOrDefault()
);

linq query trouble

Below is the code where I try to do a simple Linq-to-entities framework query, and I want to also access the results one by one:
inctDomainContext innn = new inctDomainContext();
var exx = from c in innn.cordonnes select c;
foreach (var i in exx) {
//doing something here but the programe doesn't enter the loop
}
Why doesn't the program enter into foreach loop?
it appears you're working with WCF Ria Services in Silverlight. This is totally different from how things work when using EntityFramework directly. In your case, you have to "load" the data, before being able to access it.
To do this, you have to call the "Load" method on the domain context and pass in the query you need (in your case GetCoordonneQuery()), and then you can pass a callback to be executed when the load asynchronous call is finished. The callback will have access to the results of the query. Here's an example:
....
context.Load(GetCoordonneQuery(),OnLoadCoordonneCompleted,null)
....
void OnLoadCoordonneCompleted(LoadOperation<Coordonne> loadOp)
{
foreach(var coordonne in loadOp.Entities)
{
//do something with the data
}
}
when the OnLoadCoordonneCompleted is called (i.e: when the asynchronous load call is finished), the context.Coordonnes will be loaded and contain the data you want.
Hope this helps
Are you sure there is data in there?
Try this:
inctDomainContext innn = new inctDomainContext();
bool exxAny = innn.cordonnes.Any();
Then if exxAny is false, there is no data in the collection and hence, the foreach does nothing.

LightSwitch custom query with LINQ using delegates does not work

I have problems in designing an extended query in the ...PreprocessQuery() Method of a LightSwitch query.
1st of all, I tell you in a simplified way, what works:
partial void NeedHelp_PreprocessQuery(bool Admin, ref IQueryable<Device> query)
{
// Some code...
query = query.Where<Device>(d => d.IsAvailable());
}
The query does not show any compile error and does what it should do.
Now, when I try to put the logic into a method and use its delegate in the query, there's no compile error either, but I get an exception. Here is the code:
private bool Logic(Device TheDevice, bool Admin)
{
return Admin ? true : TheDevice.IsAvailable();
}
partial void NeedHelp_PreprocessQuery(bool Admin, ref IQueryable<Device> query)
{
// Some code...
Func<Device, bool, bool> LogicDelegate = new Func<Device, bool, bool>(this.Logic);
query = query.Where<Device>(d => LogicDelegate(d, Admin));
}
The Exception is in German, I try to translate the essential:
The expression is not supported. Expression:
Invoke(value(LightSwitchApplication.ApplicationDataService+<>c__DisplayClass4).LogicDelegate, d, value(LightSwitchApplication.ApplicationDataService+<>c__DisplayClass4).Admin)
Message of inner exception:
The type "ApplicationData.Implementation.Device" cannot be used for a parameter of type "LightSwitchApplication.Device".
Since I am only using Device, I do not understand this confusion between ApplicationData.Implementation.Device and LightSwitchApplication.Device! What am I doing wrong?
Or is this kind of call simply not possible in LightSwitch?
There is no support for inline code in linq2sql - its just imagination ;).
When you do something as 'item.Trim()' behind the scenes this will be translate to the SQL command LTRIM(RTRIM(item))
You may check Views in MSSQL.

Debugging Entity Framework SQL statements

I am having a weird pattern of response time when using the Entity Framework for SQL communication.
This is from my web host:
This is from my local server:
It's the increase in response time I am worried about.
I have narrowed the problem down to one single line in code
Nop.Data > EfRepository.cs > public void Insert(T entity) > _entities.Add(entity);
Yes I know this very specific for the NopCommerce, but the point is really that I am looking her for help on how to debug this.
Are there some events I can catch that display the SQL being executed?
Or what other things can I do to find out more what is actually happening in the Entity Framework in that above command.
For debugging EF queries, the easiest thing is to cast the query to ObjectQuery and use ToTraceString:
var query = myContext.MyTable
.Where(r => r.Id == searchId)
.Select(r => r);
Console.WriteLine(((ObjectQuery)query).ToTraceString());
This will show the underlying SQL for the query, and you can run the queries manually to debug why they are slow. Here is the MSDN link:
http://msdn.microsoft.com/en-us/library/system.data.objects.objectquery.totracestring.aspx
If you're trying to get the SQL which is run when you call SaveChanges() on your context, it's not as easy. You could take a look at EFTracingProvider:
http://blogs.msdn.com/b/jkowalski/archive/2009/06/11/tracing-and-caching-in-entity-framework-available-on-msdn-code-gallery.aspx
Or, assuming you use SQL Server, you can go directly to SQL Profiler and capture the T-SQL statements (this is my preferred approach).
In EF6, you can also do this in the constructor of your dbcontext
Example
public BookServiceContext() : base("name=BookServiceContext")
{
// New code:
this.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
}
This will log to the console every SQL query EF generates. See this article for more information http://blog.oneunicorn.com/2013/05/08/ef6-sql-logging-part-1-simple-logging/
Another example might be very helpful for someone.
public class MyDbContext : DbContext
{
private readonly ILoggerFactory _loggerFactory;
public MyDbContext(DbContextOptions<MyDbContext> options, ILoggerFactory loggerFactory) : base(options)
{
_loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// Enable logging
optionsBuilder.UseLoggerFactory(_loggerFactory);
if (System.Diagnostics.Debugger.IsAttached)
optionsBuilder.EnableSensitiveDataLogging();
base.OnConfiguring(optionsBuilder);
}
}

how to replace code that uses now obsolete System.Data.OracleClient namespace classes?

I've made a "generic" program that converts data from a db to another. It uses configuration files to define the conversion. It uses code like this:
static DbProviderFactory _srcProvFactory;
static DbProviderFactory _trgtProvFactory;
public static bool DoConversions()
{
try
{
if (!InitConfig())
return false;
_srcProvFactory = DbProviderFactories.GetFactory(GetConnectionClassTypeByDatabaseType(Preferences.SourceDatabaseType));
_trgtProvFactory = DbProviderFactories.GetFactory(GetConnectionClassTypeByDatabaseType(Preferences.TargetDatabaseType));
using (DbConnection srcCnctn = _srcProvFactory.CreateConnection(),
trgtCnctn = _trgtProvFactory.CreateConnection())
{
srcCnctn.ConnectionString = Preferences.SourceConnectionString;
srcCnctn.Open();
trgtCnctn.ConnectionString = Preferences.TargetConnectionString;
trgtCnctn.Open();
//DO STUFF
}
}
}
Above GetConnectionClassTypeByDatabaseType-method return strings like "System.Data.OracleClient" depending on config file.
The DO STUFF part calls methods like one below (there's many of these) to find out database table column properties from schema. This is needed cause Oracle, SQL server etc. handle these differently.
public static int GetColumnMaxStringLength(DbProviderFactory provFactory, DataRow schemaTableRow)
{
if (provFactory is OracleClientFactory)
{
return Convert.ToInt32(schemaTableRow["LENGTH"]);
}
else if // OTHER OPTIONS
...
throw new Exception(string.Format("Unsupported DbProviderFactory -type: {0}", provFactory.GetType().ToString()));
}
So how this is supposed to be fixed now when the build says these classes are obsolete? This was supposed to be kind of text book solution when I did this (Pro C# 2008 and the
.NET 3.5 Platform). Now I'm baffled.
Thanks in advance & Best Regards - Matti
ODP.NET or any of the other 3rd party ADO.NET driver providers:
ref: Comparison of 3rd Party Oracle .NET Providers

Resources