Exposing SQL fired when LINQ executes - sql

Morning all.
Just a quick one for you - where can I find the SQL that is executed when a LINQ statement fires?
I have the following code that works a treat,
var r = (from p in getproductweightsbuyer.tblWeights
where p.MemberId == memberid &&
p.LocationId == locationid
select p);
if (buyer != "Not Specified")
r = r.Where(p => p.UnitUserField1 == buyer);
if (subcategory != "Not Specified")
r = r.Where(p => p.UnitUserField2 == subcategory);
I'm just not sure of the SQL that is firing in the conditional where clause.

If you have the database context at hand you could try:
context.GetCommand(query).CommandText

if you debug your code you can put a breakpoint and analyze the value of r, which will have the actual SQL code in it.

As well as the above options, you can also run up SQL profiler and see the actual SQL sent down the wire to the DB.

If you use LINQ to SQL you can set the DataContext.Log property. This will log the SQL when you execute the query:
getproductweightsbuyer.Log = Console.Out;
var r = (from p in getproductweightsbuyer.tblWeights
where p.MemberId == memberid &&
p.LocationId == locationid
select p);
if (buyer != "Not Specified")
r = r.Where(p => p.UnitUserField1 == buyer);
if (subcategory != "Not Specified")
r = r.Where(p => p.UnitUserField2 == subcategory);
foreach (var row in r)
...

Related

How to write Cypher query in .net core API

I have a Cypher query like that
MATCH (n: learningPaths)
WHERE any(x IN n.modules WHERE x = "any course")
RETURN n
How can I write this query in .net core API to get the results
Previously I have a query like that
MATCH (n:learningPaths)-[]->(m:modules)
WHERE m.id = "any course"
RETURN n;
and I write below in .net core API
var result = (
await _graphClient.Cypher
.Match(#"(n:learningPaths)-[]->(m:modules)")
.Where<modules>(m => m.id == "any course")
.Return((n)=> n.As<learningPaths>())
.ResultsAsync)
.ToList();
Have you tried just doing:
var query = client.Cypher
.Match("MATCH (n:learningPaths)-->(m:modules)")
.Where("any(x IN n.modules WHERE x = 'any course')"
.Return( n => n.As<learningPaths>());

IQueryable<T> to raw SQL in Entity Framework

How can I get the raw SQL generated against the below query in EF 6? I have tried ToString(), ToTraceString() but those are not working and I don't have access to the DbContext object at this point.
IQueryable<AccountApplication> query = AppService.QueryService.GetQueryMatching(spec);
var acccounts = (from a in query
where a.ApplicationId == applicationId && a.Id != 3
select new AccountDto
{
Id = a.Id,
Name = a.Account.AccountName,
ApplicationName = a.Application.ApplicationName,
SubsidaryId = a.Account.SubsidaryId.HasValue ? a.Account.SubsidaryId.Value : 0
}).ToList();
Did you try this
var sql = ((System.Data.Entity.Core.Objects.ObjectQuery)query).ToTraceString();

Filtering with Multiple DropDown Lists in MVC

I am working on 3-tier Architecture project
and I have multiple DropDown Lists to make filtering of data that is fetched from database using LINQ.
Now I need a way to filter with these dropdowns where when I select an item in any dropdown it is filtering and when I select from two dropdowns to filter by these two selections and so on...
I use linq like this:
var doctors = from d in db.Doctors
where d.CityID == id
&& d.HasSecretary == hasSec
&& d.OldSystem == oldSys
&& d.MetDoctor == metDoc
&& d.PriceProblem == priceProb
&& d.EasyToConvince == easyToCon
&& d.ComputerSavvy == comSav
&& d.Sold == sold
&& d.NotInterested == notIntr
&& d.FollowUp == followUp
&& d.NewClinic == newClin
&& d.RequestedADemo == reqDemo
select d;
And it is filtering only when I select all dropdowns, and not individually.
Please help :)
You will have to do conditional where clauses e.g.
var doctors = from d in db.Doctors;
if (id != null)
doctors = doctors.Where(d => d.CityID == id);
if (hasSec)
doctors = doctors.Where(d => d.HasSecretary == hasSec);
// other if statements
// results
var results = doctors.ToList();

WCF DataService Expand node with specified condition

I'm trying to do a simple query:
Method 1:
var ss = from h in je.RolesUsers.Expand("Role").Where(h => h.UserID == 1) select h;
Method 2:
var e = je.RolesUsers.Expand("Role").Where(s => s.UserID == 1);
I never get "Role" to be expanded in the result, it is always null.
Both lines execute the same request to the service:
http://localhost:5521/JoybaDataService.svc/RolesUsers()?$filter=cast(UserID,'Edm.Int32') eq 1&$expand=Role
Using this query I get "Role" to be expanded.
any Idea???

NHibernate - Linq query using COUNT(DISTINCT)

I'm trying to get a paged query to work properly using LINQ and NHibernate. On a single table, this works perfect, but when more than one table is joined, it's causing me havoc. Here is what I have so far.
public virtual PagedList<Provider> GetPagedProviders(int startIndex, int count, System.Linq.Expressions.Expression<Func<Record, bool>> predicate) {
var firstResult = startIndex == 1 ? 0 : (startIndex - 1) * count;
var query = (from p in session.Query<Record>()
.Where(predicate)
select p.Provider);
var rowCount = query.Select(x => x.Id).Distinct().Count();
var pageOfItems = query.Distinct().Skip(firstResult).Take(count).ToList<Provider>();
return new PagedList<Provider>(pageOfItems, startIndex, count, rowCount);
}
There are a couple issues I'm having with this. First off, the rowCount variable is pulling back a COUNT(*) on a join that has one to many. So my count is way off of what is should be, I'm expecting 129, but getting back over 1K.
The second issue I'm happening is with the results. If I'm on the first page (firstResult = 0), then I'm getting correct results. However, if firstResult is something other than 0, it produces completely different SQL. Below is the SQL generated by both scenarios, I've trimmed out some of the fat to make it a little more readable.
--firstResult = 0
select distinct TOP (30) provider1_.Id as Id12_, provider1_.TaxID as TaxID12_,
provider1_.Facility_Name as Facility5_12_, provider1_.Last_name as Last6_12_,
provider1_.First_name as First7_12_, provider1_.MI as MI12_
from PPORecords record0_ left outer join PPOProviders provider1_ on record0_.Provider_id=provider1_.Id,
PPOProviders provider2_ where record0_.Provider_id=provider2_.Id
and provider2_.TaxID='000000000'
--firstResult = 30
SELECT TOP (30) Id12_, TaxID12_, Facility5_12_, Last6_12_, First7_12_, MI12_,
FROM (select distinct provider1_.Id as Id12_, provider1_.TaxID as TaxID12_,
provider1_.Facility_Name as Facility5_12_,
provider1_.Last_name as Last6_12_,
provider1_.First_name as First7_12_,
provider1_.MI as MI12_,
ROW_NUMBER() OVER(ORDER BY CURRENT_TIMESTAMP) as __hibernate_sort_row
from PPORecords record0_ left outer join PPOProviders provider1_ on record0_.Provider_id=provider1_.Id,
PPOProviders provider2_
where record0_.Provider_id=provider2_.Id and provider2_.TaxID='000000000') as query
WHERE query.__hibernate_sort_row > 30
ORDER BY query.__hibernate_sort_row
The problem with the second query is the "distinct" keyword is not present on the outer query, only the inner query. Any ideas how to correct this?
Thanks for any suggestions!
[UPDATE]
This is the code that is building the the Linq query predicate.
private Expression<Func<Record, bool>> ParseQueryExpression(string Query) {
Expression<Func<Record, bool>> mExpression = x => true;
string[] splitQuery = Query.Split('|');
foreach (string query in splitQuery) {
if (string.IsNullOrEmpty(query))
continue;
int valStartIndex = query.IndexOf('(');
string variable = query.Substring(0, valStartIndex);
string value = query.Substring(valStartIndex + 1, query.IndexOf(')') - valStartIndex - 1);
switch (variable) {
case "tax":
mExpression = x => x.Provider.TaxID == value;
break;
case "net":
mExpression = Combine<Record>(mExpression, x => x.Network.Id == int.Parse(value));
break;
case "con":
mExpression = Combine<Record>(mExpression, x => x.Contract.Id == int.Parse(value));
break;
case "eff":
mExpression = Combine<Record>(mExpression, x => x.Effective_Date >= DateTime.Parse(value));
break;
case "trm":
mExpression = Combine<Record>(mExpression, x => x.Term_Date <= DateTime.Parse(value));
break;
case "pid":
mExpression = Combine<Record>(mExpression, x => x.Provider.Id == long.Parse(value));
break;
case "rid":
mExpression = Combine<Record>(mExpression, x => x.Rate.Id == int.Parse(value));
break;
}
}
return mExpression;
}
It seems as if the Linq provider has some "unexpected" behaviour there. I could reproduce the issue with the rowCount that you are describing and also encountered some issues when trying to fix it with a subquery.
If I understand your intentions correctly you basically want to have a paged list of Providers whose Records match certain criteria.
In that case I would suggest using a subquery. However, I tried implementing the subquery with the Query() method but it did not work. So I tried the QueryOver() method which worked flawlessly. In your case the desired queries would look like this:
Provider pAlias = null;
var query = session.QueryOver<Provider>(() => pAlias).WithSubquery
.WhereExists(QueryOver.Of<Record>()
.Where(predicate)
.And(r => r.Provider.Id == pAlias.Id)
.Select(r => r.Provider));
var rowCount = query.RowCount();
var pageOfItems = query.Skip(firstResult).Take(count).List<Provider>();
That way you do not have to struggle with the Distinct(). And as much as I personally like and use NHibernate.Linq, I suppose, if it does not work in a given situation, one should use something else that works.
Edit: Splitting the query into smaller units.
// the method ParseQueryExpression() does not need to be modified, the Expression should work like that
System.Linq.Expressions.Expression<Func<Record, bool>> predicate = x => x.Provider.TaxID == "000000000";
// Query to evaluate predicate
IQueryable<Record> queryId = session.Query<Record>().Where(predicate).Select(r => r.Provider);
// extracting the IDs to use in a subquery
List<int> idList = queryId.Select(p => p.Id).Distinct().ToList();
// total count of distinct Providers
int rowCount = idList.Count;
// new Query on Provider, using the distinct Ids
var query = session.Query<Provider>().Where(p => idList.Contains(p.Id));
// the List<Provider> to display on the page
var pageOfItems = query.Skip(firstResult).Take(count).ToList();
The problem here is that you have multiple queries and therefore multiple roundtrips to the db. Another problem apperas when you examine the generated sql. The subquery idList.Contains(p.Id) will generate an in-clause with a lot of parameters.
As you can see, these are NHibernate.Linq queries. That is because the new QueryOver feature is not a true Linq provider and does not work well with dynamic Linq expressions.
You could get around that limitation by using Detached QueryOvers. The drawback here is that you would have to modify your ParseQueryExpression() somehow, e.g. like that:
private QueryOver<Record> ParseQueryExpression(string Query)
{
Record rAlias = null;
var detachedQueryOver = QueryOver.Of<Record>(() => rAlias)
.JoinQueryOver(r => r.Provider)
.Where(() => rAlias.Provider.TaxID == "000000000")
.Select(x => x.Id);
// modify your method to match the return value
return detachedQueryOver;
}
// in your main method
var detachedQueryOver = QueryOver.Of<Record>()
.WithSubquery
.WhereProperty(r => r.Id
.In(this.ParseQueryExpression(...));
var queryOverList = session.QueryOver<Provider>()
.WithSubquery
.WhereProperty(x => x.Id)
.In(detachedQueryOver.Select(r => r.Provider.Id));
int rowCount = queryOverList.RowCount();
var pageOfItems = queryOverList.Skip(firstResult).Take(count).List();
Well, I hope you are not too confused by that.