LinQ adding unwanted (#__term_0 LIKE N'') to SQL queries - linq

I have an IQueryable extension in my User model where I'm using LINQKit :
public static IQueryable<User> ApplyFilterTerms(this IQueryable<User> query, string search)
{
if (string.IsNullOrWhiteSpace(search))
return query;
var searchTerms = search.Split(' ').Where(x => x.Length > 0).ToArray();
if (!searchTerms.Any())
return query;
var termsPredicate = searchTerms.Aggregate(
LinqExtensions.True<User>(),
(current, term) => current.And(
LinqExtensions.False<User>()
.Or(x => x.FirstName.Contains(term))
.Or(x => x.LastName.Contains(term))
.Or(x => x.UserName.Contains(term))
));
return query.Where(termsPredicate);
}
When executing this db query, LinQ translates it into something in this pattern:
DECLARE #__term_0 AS VARCHAR(100) = 'jonh'
SELECT [u].[UserId], [u].[FirstName], [u].[LastName], [u].[UserName]
FROM [Users] AS [u]
WHERE (((#__term_0 LIKE N'') OR (CHARINDEX(#__term_0, [u].[FirstName]) > 0))
OR ((#__term_0 LIKE N'') OR (CHARINDEX(#__term_0, [u].[LastName]) > 0)))
OR ((#__term_0 LIKE N'') OR (CHARINDEX(#__term_0, [u].[UserName]) > 0))
ORDER BY [u].[FirstName], [u].[LastName]
Would there be a way to remove this apparently useless (#__term_0 LIKE N'') that linq adds to the query?

Related

How to Convert a LINQ Query Syntax to a Method Syntax? (with join and multiple selects) Issue: Where-no overloads for + 3 parameters

I am trying to understand lambda expressions with Linq but i struggle with the conversion. Below is the Linq Query syntax which works just fine.
var systemUsersPoor =
(from customer in customers
join distributor in distributors
on new { customer.Location }
equals new{ distributor.Location }
where customer.Location == "UK" &&
customer.Location==distributor.Location &&
customer.Supplier == "MoneyShits" &&
distributor.Products == "ShittyCrappyCraps"
orderby customer.Name
select new
{
customerName=customer.Name , customerLocation=customer.Location, customerSupplier=customer.Supplier,
distributorName=distributor.Name, distributorProducts=distributor.Products
}).ToList();
And then in here, i have my failed attempt to convert it into a Linq Method Syntax...All works untill the .Where statement..states that it does have no definition for my fields(.location,.Supplier) and distributor
var sysUserPoor2 = customers.Join //from customer in customers Join
(
distributors, //Join on distributors on customer.Location==distribution.Location
customer=> customer.Location, //Select the primary key (the first part of the "on" clause in an sql "join" statement
distributor =>distributor.Location, // Select the foreign key (the second part of the "on" clause)
(customer, distributor) => new //select statement
{
customerName = customer.Name,
customerLocation = customer.Location,
customerSupplier = customer.Supplier,
distributorName = distributor.Name,
distributorProducts = distributor.Products
}
)
.Where
(
customer => (customer.customerLocation == "UK") &&
(customer.customerSupplier == "MoneyShits"),
distributor => distributor.distributorProducts == "ShittyCrappyCraps",
(customer, distributor) => (customer.customerLocation == distributor.Location)
);
The query with the code below works, but i dont know how to add the rest somehow...:
.Where
(
customer => (customer.customerLocation == "UK") &&
(customer.customerSupplier == "MoneyShits")
)
Please try following.
var systemUsersPoor = customers.Join(distributors,
customer => customer.Location,
distributor => distributor.Location,
(customer, distributor) => new {customer, distributor})
.Where(x => x.customer.Location.Equals("UK") &&
x.customer.Location.Equals(x.distributor.Location) &&
x.customer.Supplier.Equals("MoneyShits") &&
x.distributor.Products.Equals("ShittyCrappyCraps"))
.OrderBy(x => x.customer.Name)
.Select(x => new
{
customerName = x.customer.Name,
customerLocation = x.customer.Location,
customerSupplier = x.customer.Supplier,
distributorName = x.distributor.Name,
distributorProducts = x.distributor.Products
}).ToList();

ravendb count query not equal tolist count

ravendb query return different result for count method and tolist().count
query 1(return 9):
var count = session.Query<MobileForm,ByFormNameIndex>().Where(x => x.RequestType == RequestType.Db && x.BelongTo == oaname).ToList().Count;
query 2(return 44):
var count = session.Query<MobileForm,ByFormNameIndex>().Where(x => x.RequestType == RequestType.Db && x.BelongTo == oaname).Count();
index define:
public class ByFormNameIndex : AbstractIndexCreationTask<MobileForm>
{
public ByFormNameIndex()
{
Map = mobileForms => from form in mobileForms
select new
{
form.FormName,
form.BelongTo,
form.RequestType,
form.CreateTime,
form.Uuid
};
Analyzers.Add(x => x.FormName, "Lucene.Net.Analysis.PanGu.PanGuAnalyzer,PanGu.Lucene.Analyzer, Version=1.3.1.0, Culture=neutral, PublicKeyToken=null");
Indexes.Add(x => x.FormName, FieldIndexing.Analyzed);
Indexes.Add(x => x.BelongTo, FieldIndexing.NotAnalyzed);
Indexes.Add(x => x.RequestType, FieldIndexing.NotAnalyzed);
Indexes.Add(x => x.Uuid, FieldIndexing.NotAnalyzed);
}
}
query1 return the right count, so what's the differrent for this to method?show i new to rebuild the index to get the right result?
That is by design.
Count() will give you the total count.
ToList() gives you the first page only. And then you get the count on that.

could not resolve property (complex properties)

I have a asp.net mvc application with NHibernate and I do not know how to resolve a problem to query some data. I have this query:
// create query
var query = session.QueryOVer<Laudo>().Fetch(x => x.Equipament).Eager;
// add some filters
if (idEquipament.HasValue)
query = query.And(x => x.Equipament.Id == idEquipament.Value);
//I got the error here...
if (idCompany.HasValue)
query = query.And(x => x.Equipament.Company.Id == idCompany.Value);
When I try to execute this query, I've got an exception with this message:
"could not resolve property: Equipament.Company.Id of: DomainModel.Laudo"
what can I do to fix this problem?
Thanks
You cannot use another entity property like that. NHibernate expects expression that can be evaluated to property of the current entity. You need to use JoinQueryOver or JoinAlias to join another entity, and perform where after that.
With JoinQueryOver:
// ...
query = query.JoinQueryOver(x => x.Equipment)
.JoinQueryOver(x => x.Company)
.Where(c => c.Id == idCompany.Value);
With JoinAlias:
Equipment equipment = null;
Company company = null;
// ...
query = query.JoinAlias(x => x.Equipment, () => equipment)
.JoinAlias(() => equipment.Company, () => company)
.Where(() => company.Id == idCompany.Value);
Some more info:
What is the difference between JoinQueryOver and JoinAlias?
What can be used as a NHibernate QueryOver alias?
Complex nHibernate QueryOver expression
The tags chosen for your question make me think you didn't want to use QueryOver, but LINQ.
This is achieved by using the extension method Query, in the NHibernate.Linq namespace:
var query = session.Query<Laudo>().Fetch(x => x.Equipament);
if (idEquipament.HasValue)
query = query.Where(x => x.Equipament.Id == idEquipament.Value);
if (idCompany.HasValue)
query = query.Where(x => x.Equipament.Company.Id == idCompany.Value);

Linq to NHibernate - select count problem

Given the classes A and B where
class A
{
string Name;
Ilist<B> BList;
}
class B
{
string Name;
}
With FluentNH mapping, relationship is many-to-many which is HasManyToMany(x => x.B) for A. B has no reference to A. NH version is 2.1.2.4000.
What should be the linq query to select the collection where each row contains B.Name and count of A's containing that B? Result must be the List of anonymous type who has 2 fields: Name and Count. Result also should include all B's, hence it should be outer join.
My intend is to get the result with minimum round-trips to database, possibly in one go.
If you want to do it in Linq in one hit in code, you could do this...
var result = Session.Linq<A>()
.SelectMany(a => a.BList, (a, b) => new { b.Name, A = a.Id })
.ToList()
.GroupBy(x => x.Name)
.Select(x => new { Name = x.Key, Count = x.Count() })
.ToList();
NHibernate.Linq (2.1.2.4000) can't handle a GroupBy after a SelectMany it seems, so the first ToList pulls all the data into memory. This is inefficient -- a SQL count would be better.
Alternatively, you could add a lazy loaded collection to your B class that goes back to A. If you're using a many-to-many table in the middle, that should be easy.
public class B
{
public virtual string Name { get; set; }
public virtual IList<A> AList { get; private set; }
}
Your query simply becomes...
var result = Session.Linq<B>()
.Where(b => b.AList.Count > 0)
.Select(b => new { b.Name, b.AList.Count }
.ToList();
Which produces very efficient SQL from Linq (using a count) and gives the same result.

Why is this LINQ Where clause not returning results?

We have an entity with DateTime property DateDestroyed. A query needs to return results where this value is between nullable DateTimes startDate and endDate.
The where clauses I have are:
.Where(x => startDate.HasValue ? startDate <= x.DateDestroyed : true)
.Where(x => endDate.HasValue ? x.DateDestroyed <= endDate : true);
The query always return no results. I'm pretty sure I haven't written this query properly but don't know how it should be written or why it's not working?
My code requires IQueryable so I adapted the work by #p.campbell at ExtensionMethod.net as follows:
public static IQueryable<TSource> WhereIf<TSource>(this IQueryable<TSource> source, bool condition, Func<TSource, bool> predicate)
{
return condition ? source.Where(predicate).AsQueryable() : source;
}
public static IQueryable<TSource> WhereIf<TSource>(this IQueryable<TSource> source, bool condition, Func<TSource, int, bool> predicate)
{
return condition ? source.Where(predicate).AsQueryable() : source;
}
You could create/use an extension method for WhereIf:
Given a boolean condition, append a Where clause.
var foo = db.Customers.WhereIf(startDate.HasValue,
x => startDate <= x.DateDestroyed)
.WhereIf(endDate.HasValue,
x => x.DateDestroyed <= endDate );
More details at WhereIf at ExtensionMethod.net. You can find the code there for IEnumerable<T> and IQueryable<T>.
let's say you have a variable called "query" that you've stored the beginning part of your linq statement. Try this to dynamically construct the where clause:
if (startDate.HasValue) {
query = query.Where(x => x.DateDestroyed >= startDate);
}
if (endDate.HasValue) {
query = query.Where(x => x.DateDestroyed <= endDate);
}
LINQ works on deferred execution so the WHERE clause will correctly resolve when the code executes.
Are you always re-assigning your query with the Where() filter applied?
This pattern should work as expected:
var query = getResults();
query = query.Where(x => startDate.HasValue ? startDate <= x.DateDestroyed : true)
query = query.Where(x => endDate.HasValue ? x.DateDestroyed <= endDate : true);

Resources