How do I view the SQL generated by SubSonic SimpleRepository? - c#

I've got this toy code, works fine, using MySQL
var r = new SimpleRepository("DB", SimpleRepositoryOptions.None);
var q = r.Find<User>(x => x.UserName == "testuser");
How do I view the SQL generated by that query ?

For SQL Server, you can always run SQL Profiler to see the queries.

Unfortunately using SimpleRepository you can't do what you want without stepping into the SubSonic code. Because the Find method returns an IList it's executed before you get the chance to evaluate the SQL that's going to be executed. There are efforts underway to add this functionality in future versions of SubSonic but until then you're probably best looking at the MySQL Query Profiler.

Related

StringComparison.InvariantCultureIgnoreCase cannot be translated while used in a LINQ query

I am facing a problem executing the below query in .NET 6.
query = context.Where(user =>
user.Email.Contains(model.Email,
StringComparison.InvariantCultureIgnoreCase));
After searching the web I understood that EF Core does translate Contains for server-side evaluation - but not the overload that accepts StringComparison.InvariantCultureIgnoreCase or any other StringComparison. But never found the correct way to solve this issue
So I changed the query to something as follows to make it work:
query = context.Where(user =>
user.Email.ToLower().Contains(model.Email.ToLower());
Even though it is working I am not entirely happy with this solution and still wondering which solution solves my problem best. Would using ToLowerInvariant() be a better solution? Any better approach to solve this?
UPDATE
ToLowerInvariant() does not work and causes the same error caused by StringComparison.InvariantCultureIgnoreCase
It seems like your are writing your LINQ query on a DbSet. This is not possible as it cannot be translated to SQL statements.
You could however use the EF.Functions.Like function. This gets translated to the SQL provider and is by default case insensitive.
query = context.Where(user =>
EF.Functions.Like(user.Email, model.Email));
How your query reacts depends on the collation you set on the server side. After all your linq expressions will be translated into an SQL query and how that is interpreted will depend on your database and column settings.
What you could try is stating a collation in your query e.g.
var customers = context.Customers
.Where(c => EF.Functions.Collate(c.Name, "latin1_general_ci collation") == "John")
.ToList();
//SQL_Latin1_General_CP1_CI_AS for SQL Server
//latin1_general_ci collation for MySQL
as found in the Microsoft documentation. Where CI stands for case-insensitive (opposed to CS). Be aware that this query won't be able to leverage the index on the Name due to the custom collation. So it would be better to define it on the column (or table/database).
Try this:
query = context.Where(user => EF.Functions.Collate(user.email,
"SQL_Latin1_General_CP1_CI_AI").Contains(model.Email));

LINQ Correlated SubQuery throws Oracle Exception: Oracle 11.2.0.4.0 does not support APPLY

Here is the c# query:
qry = qry.Where(comment => idsArr.Any(
selectedId => dbv.VW_STAKEHOLDER_TYPE_XREF.Where(xref => xref.STAKE_ID == comment.STAKE_ID && xref.STAKEHOLDER_TYPE_ID == selectedId).FirstOrDefault() != null
));
From the language of the exception I am guessing that something in the c# is being translated to an apply which Oracle 11 doesn't like for some reason. I am not sure which part of the query is getting translated into APPLY and how I can circumvent this issue.
Thanks in advance.
LINQ to SQL only really works with SQL Server, although some simple queries may work on other databases. In this case the query failed as Oracle does not have a CROSS APPLY clause, but uses lateral joins instead. See this post for options when you want to use LINQ with Oracle: Is there a Way to use Linq to Oracle

C# SQL Generator to execute the new T-SQL Window Functions in SQL Server 2012?

I'm looking for a SQL Generator that can execute the new window aggregate functions that were released in SQL Server 2012. I've already looked at Subsonic and LINQ, but haven't yet taken a look at NHibernate and some others.
As an example, using the syntax in Subsonic, I'd like to do the following:
var query = new Select(Aggregate.Avg("Revenue", "MovingAverageRevenue")
.PartitionBy("Account_ID").OrderBy("Offset").RowsBetween(-5,-1)))
.From("Purchases")
.Where("MovingAverageRevenue")
.IsGreaterThan(500);
Which would translate to something like:
SELECT Aggregates.MovingAverageRevenue
FROM
(
SELECT AVG(Revenue) OVER
(PARTITION BY Account_ID
ORDER BY Offset
ROWS BETWEEN 5 PRECEDING AND 1 PRECEDING) AS MovingAverageRevenue
FROM Purchases
) Aggregates
WHERE Aggregates.MovingAverageRevenue > 500
A solution involving extending an existing ORM could also work, presumably.
Don't know for sure, but I am willing to bet that Microsoft didn't take the time to implement such constructs in LINQ-to-SQL, as there wouldn't be a need for it if LINQ-to-SQL was already working well.
I can't say much about Subsonic.

Speeding up a simple LINQ query

Is there any way of speeding up this query:
return _database.Countries
.Include("Accounts")
.Where(country => country.Accounts.Count > 0)
.ToList();
There are about 70 accounts and 70 Countries, this query takes about 1.5 seconds to execute which is quite long.
EDIT: _database is an EntityFramework model
You could try changing the Where clause to:
Where(country => country.Accounts.Any())
... but really your first port of call should be a database profiler. Look at the generated query, and put it into your favourite profiler. Check indexes etc as you would any other SQL query.
Once you've worked out why the generated SQL is slow and what you'd like the SQL to look like, then you can start working out how to change your query to generate that SQL.
You could, use sql profiler to trap the query that is being executed against the database, then using this you could optimise the scenario with indexes on the sql server.

is my linq query pulling just what it needs or everything?

I do something like this:
var src = dbContext.Set<Person>().Where(o => o.LastName.StartsWith(search));
var page = src.OrderBy(u => u.Id).Skip((page - 1) * pageSize).Take(pageSize);
var count = src.Count();
is ef pulling from the database everything and after does the query or not ? how do I know this? what are the ways finding out this?
(using ef4 ctp5 code first)
Try downloading LinqPad, it will show you the SQL that gets executed so you can see exactly what's happening.
Here's a Linq query and the results:
Here's the same Linq query along with the SQL that gets executed:
It's a very good tool for writing and optimising Linq to EF and Linq to SQL queries. It's also great for writing and testing .Net code snippets.
This tool has saved me so much time simply because you don't need to fire up the debugger! It's the most useful .Net tool that I've found in years.
None of the calls you are using is a To* operator (like ToList), so all method calls will be translated into SQL and executed in the database. However, the Count operator is immediately evaluated, you might should delay that assignment to the place you actually need the value. The other variables will be evaluated once iterated over.

Categories