public List <T> GetNextResultSet <T>()
        {
            if (!InitConnection())
            {
                if (!sqlDataReader.NextResult())
                {
                    throw new InvalidOperationException("There is no result set left");
                }
            }

            var fillVisitor = new FillVisitor(
                reader: sqlDataReader,
                db: db,
                objectFillerFactory: new ObjectFillerFactory());
            var resultSet = new List <T>();

            var configuration = GlobalDbConfiguration.GetConfigurationOrEmpty(typeof(T));
            var entityFilter  = configuration.EntityFilter;
            var queryLogger   = GlobalDbConfiguration.QueryLogger;

            while (sqlDataReader.Read())
            {
                var entity = fillVisitor.Fill <T>();

                queryLogger.IncrementLoadedElementCount(increment: 1);

                if (entityFilter.DoReturnEntity(db.Settings, entity))
                {
                    EmitValueLoaded(entity);
                    resultSet.Add(entity);
                }
            }

            return(resultSet);
        }
Exemplo n.º 2
0
        private void InitDb()
        {
            var dbConfiguration = GlobalDbConfiguration.GetConfigurationOrEmpty(typeof(TMember));

            if (dbConfiguration.GetDbForEvilLazyLoad != null)
            {
                db = dbConfiguration.GetDbForEvilLazyLoad();
            }
            else
            {
                throw new LazyLoadUnattachedEntityException("Lazy loading on a newly created entity which was not loaded from database is not allowed!");
            }
        }
Exemplo n.º 3
0
        private IReadOnlyList <object> Load(Type type, string sql, params object[] values)
        {
            List <object> entities = new List <object>();

            using (var sqlConnection = GetConnection())
            {
                using (var sqlCommand = new DbSqlCommand(sql))
                {
                    sqlCommand.Connection = sqlConnection.SqlConnection;

                    QueryHelpers.AddSqlParameters(sqlCommand, values);
                    sqlConnection.Open();

                    using (SqlDataReader reader = sqlCommand.ExecuteReader(CommandBehavior.SequentialAccess))
                    {
                        var fillVisitor = new FillVisitor(
                            reader: reader,
                            db: this,
                            objectFillerFactory: new ObjectFillerFactory());
                        while (fillVisitor.Read())
                        {
                            object entity = QueryHelpers.Fill(type, entity: null, fillVisitor: fillVisitor);
                            entities.Add(entity);
                        }
                    }
                }
            }

            var entitiesToReturn = new List <object>(entities.Count);

            var configuration = GlobalDbConfiguration.GetConfigurationOrEmpty(type);
            var entityFilter  = configuration.EntityFilter;
            var queryLogger   = GlobalDbConfiguration.QueryLogger;

            foreach (object entity in entities)
            {
                queryLogger.IncrementLoadedElementCount(increment: 1);
                if (entityFilter.DoReturnEntity(Settings, entity))
                {
                    entitiesToReturn.Add(entity);
                }
            }

            OnEntitiesLoaded(entitiesToReturn
                             .Where(e => e is DbEntity)
                             .Select(e => e as DbEntity)
                             .ToList());

            return(entitiesToReturn);
        }
Exemplo n.º 4
0
        private bool ShouldUpdateColumn <TDbEntity, TId>(
            ref DbValue <TId> column,
            TId value,
            ref IDbEntityRef <TDbEntity> dbEntityRef,
            Func <long> getValueAsLongOrZero)
            where TDbEntity : DbEntity
        {
            if (EqualityComparer <TId> .Default.Equals(column.Entity, value))
            {
                return(false);
            }

            if (!_allowSettingColumns)
            {
                var writeDb = _db as WriteDb;
                if (writeDb != null && writeDb.Settings.ReturnPreviouslyLoadedEntity_Obsolete)
                {
                    if (column.ValueWasAssigned() || (dbEntityRef != null && dbEntityRef.HasAssignedValue))
                    {
                        // we do not want to modify updated entities by returning them again with a query
                        return(false);
                    }
                }

                throw new InvalidOperationException(
                          "Review your query. It smells wrong! Most probably you used UnionDb() with queries that have different columns.");
            }

            if (dbEntityRef != null)
            {
                if (dbEntityRef is DbEntityRefCached <TDbEntity> )
                {
                    dbEntityRef = GlobalDbConfiguration.GetConfigurationOrEmpty(GetType()).CacheService.GetDbEntityRefCached <TDbEntity>((int)getValueAsLongOrZero());
                }
                else
                {
                    dbEntityRef.ResetValue();
                }
            }

            return(true);
        }
Exemplo n.º 5
0
        protected IDbEntityRef <TMember> GetDbEntityRef <TMember>(
            bool isForeignKey,
            string[] idColumnNames,
            Func <long?>[] entityIds,
            Action <TMember> beforeRightsCheckAction) where TMember : DbEntity
        {
            IDbEntityRef <TMember> dbEntityRef = null;

            if (_getChildrenFromCache && entityIds.Length == 1)
            {
                var entityId = entityIds[0]();
                if (entityId.HasValue)
                {
                    if (idColumnNames.Length != 1 ||
                        idColumnNames[0] != "[Id]")
                    {
                        throw new InvalidOperationException("Getting the reference by foreign key is broken. If you get here, this is probably a follow up problem because of an error that happened earlier.");
                    }

                    if (typeof(IId).IsAssignableFrom(typeof(TMember)) && entityId.Value <= int.MaxValue)
                    {
                        dbEntityRef = GlobalDbConfiguration.GetConfigurationOrEmpty(GetType()).CacheService.GetDbEntityRefCached <TMember>((int)entityId.Value);
                    }
                }
                else
                {
                    return(null);
                }
            }

            if (dbEntityRef == null)
            {
                dbEntityRef = new DbEntityRef <TMember>(DbInternal, isForeignKey, idColumnNames, entityIds, _lazyLoadChildren, _getChildrenFromCache);
            }

            return(dbEntityRef);
        }
Exemplo n.º 6
0
 private IDbEntityValidator GetValidationHandler()
 {
     return(GlobalDbConfiguration.GetConfigurationOrEmpty(GetType()).Validator);
 }
Exemplo n.º 7
0
        private void EnsureElementsAreLoaded()
        {
            if (cachedElements != null)
            {
                return;
            }

            lock (cachedElementsLock)
            {
                if (cachedElements != null)
                {
                    return;
                }

                var cachedTypedElements = new List <TElement>();
                List <(TElement, List <object>)> loadedData = SqlCommands.ExecuteSqlCommand(() =>
                {
                    using (var sqlConnection = Db.GetConnection())
                    {
                        using (var sqlCommand = GetSqlCommand())
                        {
                            QueryHelpers.AddSqlParameters(sqlCommand, parameters);

                            // AppContext.StartRequestTiming(sql, "OpenConnection");
                            sqlConnection.Open();
                            // AppContext.StopRequestTiming(sql, "OpenConnection");

                            sqlCommand.Connection = sqlConnection.SqlConnection;
                            // sqlCommand.Transaction = sqlConnection.SqlConnection.BeginTransaction(Db.Settings().IsolationLevel);

                            if (sqlCommand.CommandType == CommandType.StoredProcedure)
                            {
                                SqlParameter returnValue = SqlParameterUtils.Create("@ReturnValue", TypeToDbType <TElement>());
                                returnValue.Direction    = ParameterDirection.ReturnValue;
                                sqlCommand.Parameters.Add(returnValue);
                                sqlCommand.ExecuteNonQuery();

                                TElement entity = (TElement)sqlCommand.Parameters["@ReturnValue"].Value;
                                cachedTypedElements.Add(entity);

                                sqlCommand.Parameters.Clear();
                                return(new List <(TElement, List <object>)>());
                            }
                            else
                            {
                                // AppContext.StartRequestTiming(sql, "ExecuteReader");

                                var loadedDataFromReader = new List <(TElement, List <object>)>();
                                using (SqlDataReader reader = sqlCommand.ExecuteReader(CommandBehavior.SequentialAccess))
                                {
                                    // AppContext.StopRequestTiming(sql, "ExecuteReader");
                                    // AppContext.StartRequestTiming(sql, "FillVisitor");

                                    var fillVisitor = new FillVisitor(
                                        reader: reader,
                                        db: Db,
                                        objectFillerFactory: new ObjectFillerFactory());
                                    // fillVisitor.SQL = sql;

                                    // AppContext.StopRequestTiming(sql, "FillVisitor");
                                    // AppContext.StartRequestTiming(sql, "Read");
                                    int k = 0;
                                    while (fillVisitor.Read())
                                    {
                                        // AppContext.StopRequestTiming(sql, "Read");
                                        // AppContext.StartRequestTiming(sql, "Fill", k > 0);

                                        TElement entity = QueryHelpers.Fill(default(TElement), fillVisitor);
                                        var dbEntity    = entity as DbEntity;
                                        if (dbEntity != null)
                                        {
                                            ((IDbEntityInternal)dbEntity).SetAllowSettingColumns(false);
                                        }

                                        if (entity is IId)
                                        {
                                            entity = (TElement)Db.LoadedEntityCache.GetOrAdd(typeof(TElement), "Id", ((IId)entity).Id, entity);
                                        }

                                        // AppContext.StopRequestTiming(sql, "Fill");

                                        // First fetch all entities from the db and then return them
                                        // Otherwise we have problems, if someone calls AnyDb() first (AnyDb() just requests the first entity)
                                        // Anyway we improve performance if someone calls the query two times: The second time, we don't query the
                                        // database but return the cached elements

                                        List <object> subEntities = new List <object>();
                                        if (fillVisitor.HasNext && !fillVisitor.IsDBNull())
                                        {
                                            subEntities.OfType <IDbEntityInternal>().ForEach(e => e.SetAllowSettingColumns(true));
                                            // AppContext.StopRequestTiming(sql, "subEntities");
                                        }

                                        k++;
                                        loadedDataFromReader.Add((entity, subEntities));
                                        // CachedElements.Add(entity);
                                    }

                                    // AppContext.StopRequestTiming(sql, "Read");
                                }

                                sqlCommand.Parameters.Clear();
                                return(loadedDataFromReader);
                            }
                        }
                    }
                });

                // Connect the items to one another (i.e. if Person.Customer was called, set Person.Customer to the recently loaded entity)
                // First emit EmitValueLoadedBeforeRightsCheck(dbEntity); for all entities before checking the rights, because if only do it within the while loop below just before Db.ReturnEntity for each dbEntity,
                // in GetOwnerMandatorId() of i.e. User (which is called from Db.ReturnEntity()), if we call Person.Customer.MandatorId, Customer is loaded from the DB, because Person.Customer was not set yet
                loadedData.Select(e => e.Item1).OfType <DbEntity>().ForEach(e => EmitValueLoadedBeforeRightsCheck(e));
                // Do this after the sql connection above has been closed
                // Otherwise we get this exception:
                // System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Transactions.TransactionAbortedException: The transaction has aborted. ---> System.Transactions.TransactionPromotionException: Failure while attempting to promote transaction. ---> System.Data.SqlClient.SqlException: There is already an open DataReader associated with this Command which must

                var entityFilter = GlobalDbConfiguration.GetConfigurationOrEmpty(typeof(TElement)).EntityFilter;
                for (int i = 0; i < loadedData.Count; i++)
                {
                    var entity         = loadedData[i].Item1;
                    var joinedEntities = loadedData[i].Item2;

                    GlobalDbConfiguration.QueryLogger.IncrementLoadedElementCount(increment: 1);
                    // Count the joined entities too
                    GlobalDbConfiguration.QueryLogger.IncrementLoadedElementCount(increment: joinedEntities?.Count ?? 0);

                    var dbEntity = entity as DbEntity;
                    if (dbEntity != null)
                    {
                        ((IDbEntityInternal)dbEntity).SetAllowSettingColumns(allowSettingColumns: true);
                    }

                    if (entityFilter.DoReturnEntity(Db.Settings, entity, joinedEntities))
                    {
                        EmitValueLoaded(dbEntity);
                        cachedTypedElements.Add(entity);
                    }
                    else
                    {
                        EmitValueRemoved(dbEntity);
                    }
                }

                cachedElements = cachedTypedElements.AsReadOnly();
            }
        }