DbLinq / dblinq2007

LINQ provider for Oracle, PostgreSQL, MySQL, Ingres, SQLite, Firebird and ... SQL Server
Other
62 stars 31 forks source link

QueryCacheEnabled=true caches DataContext #223

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Problem:
QueryBuilder.SetInSelectCache stores a SelectQuery.
SelectQuery.DataContext holds the actual DataContext.
Since DataConext is a short living object, and could be destroyed, this is
a source for errors.

What steps will reproduce the problem?
A pattern like:
            using (var context1 = CreateDB()) {
                var employee = context1.Employees.First(r => r.LastName ==
"Fuller");
// ... make some changes here
                context1.SubmitChanges();
            }

            using (var context2 = CreateDB()) {
                var employee = context2.Employees.First(r => r.LastName ==
"Fuller");
// context1 is used, as SelectQuery stores context1

                context2.SubmitChanges();
            }

What is the expected output? What do you see instead?
Sometimes - I am very sorry that I couldn't extract a testcase - changes
are not available in the second query. 

What version of the product are you using? On what operating system?
r1342, Windows XP, !MONO_STRICT

Please provide any additional information below.
The problem can be solved by the following changes in 
**** QueryBuilder.SetInSelectCache:

        protected virtual void SetInSelectCache(ExpressionChain
expressions, SelectQuery query){
            var cache = QueryCache;
            // **** CHANGED: dont cache the dataContext. It is a short
living object and should not be cached! 
            query = new SelectQuery(null, query.Sql, query.InputParameters,
query.RowObjectCreator,
                         query.ExecuteMethodName);
            cache.SetInSelectCache(expressions, query);
        }

**** QueryBuilder.GetSelectQuery
        public SelectQuery GetSelectQuery(ExpressionChain expressions,
QueryContext queryContext)
        {
            SelectQuery query = null;
            if (queryContext.DataContext.QueryCacheEnabled)
            {
                query = GetFromSelectCache(expressions);
            }
            if (query == null)
            {
                Profiler.At("START: GetSelectQuery(), building Expression
query");
                var expressionsQuery = BuildExpressionQuery(expressions,
queryContext);
                Profiler.At("END: GetSelectQuery(), building Expression
query");

                Profiler.At("START: GetSelectQuery(), building Sql query");
                query = BuildSqlQuery(expressionsQuery, queryContext);
                Profiler.At("END: GetSelectQuery(), building Sql query");

                if (queryContext.DataContext.QueryCacheEnabled)
                {
                    SetInSelectCache(expressions, query);
                }
            } else {
                if (query.InputParameters.Count > 0) {

                    Profiler.At("START: GetSelectQuery(), building
Expression parameters of cached query");
                    var parameters = BuildExpressionParameters(expressions,
queryContext);
                    Profiler.At("END: GetSelectQuery(), building Expression
parameters of cached query");

// **** CHANGED: use the queryContext.DataContext instead of query.DataContext:
                    query = new SelectQuery(queryContext.DataContext,
query.Sql, parameters, query.RowObjectCreator,
                                             query.ExecuteMethodName);

                }
// **** CHANGED: if there are no parameters, we have to renew the
DataContext too
else {
                    query = new SelectQuery(queryContext.DataContext,
query.Sql, query.InputParameters, query.RowObjectCreator,
                         query.ExecuteMethodName);
                }
            }
            return query;
        }

cheers,
lytico
http://limada.sourceforge.net/

Original issue reported on code.google.com by lyt...@gmail.com on 3 Apr 2010 at 3:15

GoogleCodeExporter commented 9 years ago
Yet another reason it should be disabled by default.  It's buggy as hell.

Original comment by jonmpr...@gmail.com on 8 Apr 2010 at 1:17

GoogleCodeExporter commented 9 years ago
but it gives up to 50% faster performance in my usecase.
for me it works with the patch - until now.

Original comment by lyt...@gmail.com on 9 Apr 2010 at 7:24