Linq to Entity Framework with Informix generates useless CAST - entity-framework

I have the following Linq query:
var asnPacApoRepository = repoFactory.GetRepository<asn_pac_apo>();
var query = asnPacApoRepository.Table
.Where(_ => positionList.Contains(_.pzn) && _.gueltig_von <= date &&
(date <= _.gueltig_bis || _.gueltig_bis == null));
This generates the SQL query:
SELECT *
FROM informix.asn_pac_apo AS Extent1
WHERE ((((CAST('06460518' AS nvarchar(8)) = Extent1.pzn) OR (CAST('10710808' AS nvarchar(8)) = Extent1.pzn)) OR ((CAST('00584142' AS nvarchar(8)) = Extent1.pzn) OR (CAST('03728156' AS nvarchar(8)) = Extent1.pzn))) AND (Extent1.gueltig_von <= '2016-04-24')) AND (('2016-04-24' <= Extent1.gueltig_bis) OR (Extent1.gueltig_bis IS NULL))
The issue with the generated query is performance, because the pzn column is of type:
and it is indexed, but the statement: CAST('06460518' AS nvarchar(8)) makes the index not to be used.
I was expecting Linq to generate the following query:
SELECT *
FROM informix.asn_pac_apo AS Extent1
WHERE (Extent1.pzn IN ('06460518','10710808','00584142','03728156') AND (Extent1.gueltig_von <= '2016-04-24')) AND (('2016-04-24' <= Extent1.gueltig_bis) OR (Extent1.gueltig_bis IS NULL));
If I create a linq query with Equals instead of Contains, the cast does not appear, and the SQL generated query is as expected.
How can I get rid of this useless CAST statement?
I set in .edmx the property Unicode=True:
but this doesn't seem to affect in any way the generated model, nor the generated query.
As a note, I use the old ObjectContext for my EF model and the database type is INFORMIX.

Related

Entity Framework Core Count unrelated records in another table

I need to count how many records in the tableA are not in the tableA, how to do this with LINQ?
with SQL I do the following way
select count(*) as total from produtoitemgrade g
where g.id not in (select idprodutograde from produtoestoque where idProduto = 12)
and g.idProduto = 12
my linq code so far.
var temp = (from a in Produtoitemgrades
join b in Produtoestoques on a.IdUnico equals b.IdUnicoGrade into g1
where g1.Count(y => y.IdProduto == 12)>0 && !g1.Any()
select a).ToList();
I tried to follow that example LINQ get rows from a table that don't exist in another table when using group by?
but an error occurs when running, how can I do this?
Thanks!
Your query should looks like the following, if you want to have the same SQL execution plan:
var query =
from a in Produtoitemgrades
where !Produtoestoques.Where(b => a.IdUnico == b.IdUnicoGrade && b.idProduto == 12).Any()
&& a.idProduto == 12
select a;
var result = query.Count();

Linq order by using query expression

Is it possible to do orderby expression using linq query expression based on dynamic string parameter? because the query i have is producing weird SQL query
my linq:
var product = from prod in _context.Products
join cat in _context.Categories on prod.CategoryId equals cat.CategoryId
join sup in _context.Suppliers on prod.SupplierId equals sup.SupplierId
orderby sortParam
select new ProductViewModel
{
ProductName = prod.ProductName,
ProductId = prod.ProductId,
QuantityPerUnit = prod.QuantityPerUnit,
ReorderLevel = prod.ReorderLevel,
UnitsOnOrder = prod.UnitsOnOrder,
UnitPrice = prod.UnitPrice,
UnitsInStock = prod.UnitsInStock,
Discontinued = prod.Discontinued,
Category = cat.CategoryName,
Supplier = sup.CompanyName,
CategoryId = cat.CategoryId,
SupplierId = sup.SupplierId
};
where var sortParam = "prod.ProductName"
The code above produces weird sql where order by sortParam is being converted to (SELECT 1). Full query catched by sql profiler below:
exec sp_executesql N'SELECT [prod].[ProductName], [prod].[ProductID], [prod].[QuantityPerUnit], [prod].[ReorderLevel], [prod].[UnitsOnOrder], [prod].[UnitPrice], [prod].[UnitsInStock], [prod].[Discontinued], [cat].[CategoryName] AS [Category], [sup].[CompanyName] AS [Supplier], [cat].[CategoryID], [sup].[SupplierID]
FROM [Products] AS [prod]
INNER JOIN [Categories] AS [cat] ON [prod].[CategoryID] = [cat].[CategoryID]
INNER JOIN [Suppliers] AS [sup] ON [prod].[SupplierID] = [sup].[SupplierID]
ORDER BY (SELECT 1)
OFFSET #__p_1 ROWS FETCH NEXT #__p_2 ROWS ONLY',N'#__p_1 int,#__p_2 int',#__p_1=0,#__p_2=10
I'm seeing a lot of people doing linq order by using dynamic parameter but all of them use lambda not query expression, please enlighten me
As was already mentioned, you are passing a string value instead of an expression that reflects the column name. There are options for what you want however, see for example here.

why my Linqued query is not getting executed

I have this linqued query
var moreThen1dayLeavefed = (from LApp in db.LeaveApplications
join Emp in db.Employees
on LApp.Employee equals Convert.ToInt32(Emp.EmployeeNumber)
join LBrk in db.LeaveBreakups
on LApp.Id equals LBrk.LeaveApplication
where Emp.Team == 8 && LBrk.StartDate.Year == 2015 && LBrk.StartDate.Month == 5
select new { StartDate = LBrk.StartDate.Day, EndDate = LBrk.EndDate.Day, diff = (DbFunctions.DiffDays(LBrk.StartDate, LBrk.EndDate) + 1) }).ToList();
it gives error
LINQ to Entities does not recognize the method 'Int32 ToInt32(System.String)' method, and this method cannot be translated into a store expression.
on line 3, i.e
on LApp.Employee equals Convert.ToInt32(Emp.EmployeeNumber)
as I am converting the string to int during inner join
Just saw your related question. Your EmployeeNumber field seems to be filled with fixed size (5) zero left padded string representation of a number. If that's true, you can use the trick from how to sort varchar column containing numeric values with linq lambdas to Entity to solve the issue.
Just replace
on LApp.Employee equals Convert.ToInt32(Emp.EmployeeNumber)
with
on DbFunctions.Right("0000" + LApp.Employee.ToString(), 5) equals Emp.EmployeeNumber

Linq to entities subquery

How can I write the following subquery in Linq:
Context.Set<Process>()
.Include(...)
.Where(x => x.Activity.Name.CompareTo(Context.Set<Activity>().Where(a => a.Id == activityId).Select(c => a.Name)) > 0)
.Take(1);
This is a simplifed version of query, WHERE clause only includes the part that is not working. If I change Context.Set().... subquery to a string constant, then the query works. As it is, it gives NotSupportedException
LINQ to entities does not recognize method Set<Activity>
Try this:
(from p in context.Set<Process>().Include(...)
from a in context.Set<Activity>()
where a.Id == activityId
where p.Activity.Name.CompareTo(a.Name) > 0
select p).Take(1);

How to implement raw sql query in Tastypie

I am trying to do this simple query, but it does not work. Thanks.
SELECT * FROM TSimple where (start_date < '2012-04-20' and end_date is null) or
(end_date > '2012-04-20' and start_date < '2012-04-20')
class TSimple (models.Model):
start_date = models.DateTimeField()
end_date = models.DateTimeField(blank=True, null=True)
...
class TSimpleResource(ModelResource):
def dehydrate(self, bundle):
request_method = bundle.request.META['REQUEST_METHOD']
if request_method=='GET':
new_date = bundle.request.GET.get('new_date', '')
qs = TSimple.objects.raw(
'SELECT * FROM TSimple where (start_date<=\'' +
new_date + '\' and end_date>=\'' +
new_date + '\') or (start_date<=\'' + new_date +
'\' and end_date is null)')
ret_list = [row for row in qs]
// NOT WORK. Not able to get correct json data in javascript.
// It needs return bundle. HOW to replace bundle?
// Is this correct way to do it?
return ret_list
else:
// This is ok.
return bundle
I have following questions:
1) (raw sql method) If implementing in dehydrate method is correct way to do it? If it is, above does not work. It should return bundle object. How to construct new bundle?
If above method is ok, I noticed that bundle already constructed .data field with default query(?), which will be thrown away with new query. That raise the questions if this is right way to do it.
2) If there are other raw sql method to do it? Where to execute the sql?
3) How to do it in filter?
4) I know sql and not familiar with complex filter. That's why I am trying to use raw sql method to do quick prototype. What are the draw back? I noticed that using Tastypie has many unnecessary queries which I don't know how to get rid of it. Example, query on table with foreign key trigger query to another table's data, which I don't want to get.
I figure out the filter and it seems worked. But I am still interested in raw sql.
def apply_filters(self, request, applicable_filters):
base_filter = super(TSimpleResource, self).apply_filters(request,
applicable_filters)
new_date = request.GET.get('new_date', None)
if new_date:
qset = (
(
Q(start_date__lte=new_date) &
Q(end_date__gte=new_date)
) |
(
Q(start_date__lte=new_date) &
Q(end_date__isnull=True)
)
)
base_filter = base_filter.filter(qset)
return base_filter