Linq Conditional Where clause - linq-to-sql

While searching for linq conditional where clause, I found this article, the way they use is like below:
var logs = from log in context.Logs
select log;
if (filterBySeverity)
logs = logs.Where(p => p.Severity == severity);
if (filterByUser)
logs = logs.Where(p => p.User == user);
but I was wondering is this method efficient? How many queries would linq perform?

Yes, I think this is efficient. No queries will actually be performed by this code, because it doesn't try to read anything from 'logs'. When it does, it should take both conditions into account in the same query (i.e. a WHERE clause that includes both conditions).
BUT, if you are using LINQ and worried about efficiency, you really have to check everything you write by using tools to look at what queries actually get run. You can do this using SQL Server Profiler.

You can use dynamic LINQ (ScottGu's Article)
So you can easily create your where clause in string and then pass it to the Where method:
public string GetWhereClause()
{
string whereClause = "";
....
return whereClause
}
var logs = context.Logs.Where( GetWhereClause() );
Hope this helps ;)

Related

how to deal query that mysql json data type as condition with spring-data-jpa

With mysql, there is a column used json data type. i want to execute query with the column as condition. With Sql, i can write it like bellow.
select * from user where json_extract(address,'$.city')= 'beijing'
But using spring-data-jpa, i don't know how to implement it. JPQL have no provided some api implement json_extract. And the JpaSpecificationExecutor of jpa have not provide same function too. If someone know how to do it, please answer this question.
Try this:
#Query(value = "select * from user where json_extract(address,'$.city') = '?city'", nativeQuery = true)
List<User> findUsersByCity(String city);
I didn't check it.
Good luck

mysql performance difference between where id = vs where id IN()

I am very new to mysql . I had a query, from this query i am getting some stock_ids.In the second query i need to pass those stock_ids. For this i am fetching all the stock_ids in a array.Now my question is in which way can i pass those stock_ids to the second query. For this i have two approaches.
First approach:
$array_cnt = count($stockid_array);
for($i = 0; $i<$array_cnt;$i++)
{
$sql = "select reciever_id,sender_identifier,unique_stock_id,vat_number,tax_number from stocktable where stock_id = '".$stockid_array[$i]."'";
// my while loop
}
Another approach is
$sql = "reciever_id,sender_identifier,unique_stock_id,vat_number,tax_number from stocktable where stock_id in ('1','2','3','4','5','6','7','8','9');
//while loop comes here.
So which approach gives good performance ? Please guide me.
MySQL has a nice optimization for constants in an in list -- it basically sorts the values and uses a binary search. That means that the in is going to be faster. Also, in can take advantage of an index on the column.
In addition, running a single query should be faster than running multiple queries.
So, the in version should be better than running multiple queries with =.

How best to retrieve result of SELECT COUNT(*) from SQL query in Java/JDBC - Long? BigInteger?

I'm using Hibernate but doing a simple SQLQuery, so I think this boils down to a basic JDBC question. My production app runs on MySQL but my test cases use an in memory HSQLDB. I find that a SELECT COUNT operation returns BigInteger from MySQL but Long from HSQLDB.
MySQL 5.5.22
HSQLDB 2.2.5
The code I've come up with is:
SQLQuery tq = session.createSQLQuery(
"SELECT COUNT(*) AS count FROM calendar_month WHERE date = :date");
tq.setDate("date", eachDate);
Object countobj = tq.list().get(0);
int count = (countobj instanceof BigInteger) ?
((BigInteger)countobj).intValue() : ((Long)countobj).intValue();
This problem of the return type negates answers to other SO questions such as getting count(*) using createSQLQuery in hibernate? where the advice is to use setResultTransformer to map the return value into a bean. The bean must have a type of either BigInteger or Long, and fails if the type is not correct.
I'm reluctant to use a cast operator on the 'COUNT(*) AS count' portion of my SQL for fear of database interoperability. I realise I'm already using createSQLQuery so I'm already stepping outside the bounds of Hibernates attempts at database neutrality, but having had trouble before with the differences between MySQL and HSQLDB in terms of database constraints
Any advice?
I don't known a clear solution for this problem, but I will suggest you to use H2 database for your tests.
H2 database has a feature that you can connect using a compatibility mode to several different databases.
For example to use MySQL mode you connect to the database using this jdbc:h2:~/test;MODE=MySQL URL.
You can downcast to Number and then call the intValue() method. E.g.
SQLQuery tq = session.createSQLQuery("SELECT COUNT(*) AS count FROM calendar_month WHERE date = :date");
tq.setDate("date", eachDate);
Object countobj = tq.list().get(0);
int count = ((Number) countobj).intValue();
Two ideas:
You can get result value as String and then parse it to Long or BigInteger
Do not use COUNT(*) AS count FROM ..., better use something like COUNT(*) AS cnt ... but in your example code you do not use name of result column but it index, so you can use simply COUNT(*) FROM ...

How efficient is it to call a UDF and sproc from within my LINQ to SQL?

I ran into an issue where I need to call a UDF within my LINQ to SQL and then another stored procedure within that. Here's the code.
public IQueryable<DataDTO> GetLotsaData(string dataId, DateTime date, string custIDs)
{
var data = (from rs in _context.spXI_GetData(dataId, date, custIDs)
select new DataDTO
{
Time = rs.Time,
TimeZone = _context.GetTimezone(postDate, _context.GetDetailedData(rs.PKID, custIDs).FirstOrDefault().Zip),
CompletedTime = rs.Completed_Time,
});
return data.AsQueryable<DataDTO>();
}
The line I'm worried about is the one where I'm calling the GetTimezone UDF. Is it inefficient to call a UDF in the middle of a LINQ query and then another stored procedure (GetDetailedData) to get a single value for that UDF? What kind of SQL would this generate?
It looks a bit convoluted to me, but still better than the alternative which would be a sub-select or join in my stored procedure. (I'm trying to avoid having my stored procedure return the new field - TimeZone - instead just having it returned in my DTO.) And yes, I realize this could all be avoided if we were using UTC. Sadly, I have no control over that.
Why can't spXI_GetData return the complete result set? I'd say that would be optimal in this situation.
The GetTimezone and GetDetailedData functions will be called for every row in the spXI_GetData set. Would be better if the GetTimezone function could return a inline table and than you could join with it instead.

LinqToSql - Parallel - DataContext and Parallel

In .NET 4 and multicore environment, does the linq to sql datacontext object take advantage of the new parallels if we use DataLoadOptions.LoadWith?
EDIT
I know linq to sql does not parallelize ordinary queries. What I want to know is when we specify DataLoadOption.LoadWith, does it use parallelization to perform the match between each entity and its sub entities?
Example:
using(MyDataContext context = new MyDataContext())
{
DataLaodOptions options =new DataLoadOptions();
options.LoadWith<Product>(p=>p.Category);
return this.DataContext.Products.Where(p=>p.SomeCondition);
}
generates the following sql:
Select Id,Name from Categories
Select Id,Name, CategoryId from Products where p.SomeCondition
when all the products are created, will we have a
categories.ToArray();
Parallel.Foreach(products, p =>
{
p.Category == categories.FirstOrDefault(c => c.Id == p.CategoryId);
});
or
categories.ToArray();
foreach(Product product in products)
{
product.Category = categories.FirstOrDefault(c => c.Id == product.CategoryId);
}
?
No, LINQ to SQL does not. There is little to parallelize on the .NET side. All LINQ to SQL does is translating expression trees to SQL queries. SQL Server will execute those SQL statements, and is able to do this in parallel.
Don't forget that while you can do something like this with your LINQ to SQL LINQ query, it isn't a good idea:
// BAD CODE!!! Don't parallelize a LINQ to SQL query
var q =
from customer in db.Customers.AsParallel()
where customer.Id == 5
select customer;
While this yields the correct results, you won't get the performance improvement you are hoping for. PLINQ isn't able to handle IQueryable objects. Therefore, it will just handle an IQueryable as an IEnumerable (thus iterating it). It will process the db.Customers collection in parallel and use multiple threads to filter the customers. While this sounds okay, this means it will retrieve the complete collection of customers from the database! Without the AsParallel construct, LINQ to SQL would be able to optimize this query by adding the WHERE id = #ID to the SQL. SQL Server would than be able to use indexes (and possibly multiple-threads) to fetch the values.
While there is some room for optimization inside the LINQ to SQL engine when it comes to matching entities to its sub entities, there doesn't seem such optimization in the framework currently (or at least, I wasn't able to find any using Reflector).