Exemplo n.º 1
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.º 2
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.º 3
0
 protected void UpdateColumnIfDifferent <TDbEntity, TId>(ref DbValue <TId?> column, TId?value, ref IDbEntityRef <TDbEntity> dbEntityRef)
     where TDbEntity : DbEntity
     where TId : struct
 {
     if (ShouldUpdateColumn(ref column, value, ref dbEntityRef, () => (value as long?) ?? 0))
     {
         column.Entity = value;
     }
 }
Exemplo n.º 4
0
        /// <summary>
        /// DbEntity Assignment
        /// </summary>
        /// <typeparam name="TEntityToSet">Type of entity to assign ("Item" if i set ItemProduct.Item)</typeparam>
        /// <typeparam name="TThisEntity">Type of this entity entity ("ItemProduct" if i set ItemProduct.Item)</typeparam>
        /// <param name="newValue">This entity gets assigned to the object (righthand side of the =)</param>
        /// <param name="newValueId">Id or Null of newValue</param>
        /// <param name="reference">This newValue gets assigned to this object (lefthand side of the =)</param>
        /// <param name="referenceIdSetter"></param>
        /// <param name="otherSideSet"></param>
        /// <param name="setOtherSideEntity">Method to be applied on the new value</param>
        /// <param name="idChangedAction">Method to be applied if id Changed</param>
        /// <param name="referenceIdValue"></param>
        protected void AssignDbEntity <TEntityToSet, TThisEntity>(
            TEntityToSet newValue,
            long?[] newValueId,
            IDbEntityRef <TEntityToSet> reference,
            long?[] referenceIdValue,
            Action <long?>[] referenceIdSetter,
            Func <TEntityToSet, IDbEntitySet <TThisEntity> > otherSideSet,
            Action <TEntityToSet, TThisEntity> setOtherSideEntity,
            EventHandler idChangedAction)
            where TEntityToSet : DbEntity
            where TThisEntity : DbEntity
        {
            if (!_lazyLoadChildren && newValue != null && newValue._lazyLoadChildren)
            {
                throw new InvalidOperationException($"Lazy loading of {typeof(TEntityToSet).Name} is disabled, so is the assignment");
            }

            if (newValue != null && !newValue._lazyLoadChildren && _lazyLoadChildren)
            {
                throw new InvalidOperationException(
                          "Cannot assign an entity of type {typeof(TEntityToSet).Name} which has _lazyLoadChildren == false");
            }

            TEntityToSet previousValue = (reference.HasLoadedValue || reference.HasAssignedValue) ? reference.GetEntity(null) : null;

            // 2TK BDA INotifyDeveloper Event o.Ä
//#if DEBUG
//            if (WarnDeveloperIfEntitiesAlreadyConnected
//                && MachineInfo.IsDevelopmentMachine
//                && previousValue != null
//                && !ReferenceEquals(previousValue, newValue))
//            {
//                if (Debugger.IsAttached)
//                {
//                    // Entity ist bereits da. Es wurde bereits vorher zugegriffen was nicht gut ist
//                    Debugger.Break();
//                }
//            }

//#endif
            var idEntity    = previousValue as ILongId;
            var newIdEntity = newValue as ILongId;

            if (previousValue != null &&
                newValue != null &&
                idEntity != null &&
                newValue != null &&
                (((idEntity).Id > 0 && (idEntity).Id == (newIdEntity)?.Id) || // Entity from the database; even if it is loaded again, we assume it is the same
                 ((idEntity).Id == 0 && ReferenceEquals(previousValue, newValue))))       // Newly created entity
            {
                return;
            }

            var referenceIsForeignKey = ((IDbEntityRefInternal)reference).IsForeignKey;

            // Special case. Entity is explicitly set to null (we must know that the entity was set)
            if (!reference.HasLoadedValue && !reference.HasAssignedValue && newValue == null)
            {
                reference.SetEntity(null);
                if (referenceIsForeignKey)
                {
                    for (int i = 0; i < referenceIdValue.Length; i++)
                    {
                        if (referenceIdValue[i].HasValue)
                        {
                            // In order that IdChanged() or similar events are called, we assign the property instead of directly the referenceIdValue
                            referenceIdSetter[i](null);
                        }
                    }
                }

                return;
            }

            // Special case. Foreign key set to null for 1-1 relations
            if ((reference.HasLoadedValue || reference.HasAssignedValue) &&
                newValue == null &&
                !referenceIsForeignKey &&
                !ReferenceEquals(previousValue, newValue) &&
                otherSideSet == null)
            {
                if (setOtherSideEntity != null)
                {
                    setOtherSideEntity(previousValue, null);
                }
                reference.SetEntity(null);
                return;
            }

            // 1-N relations
            if (!ReferenceEquals(previousValue, newValue) ||
                (otherSideSet != null && (!(reference.HasLoadedValue || reference.HasAssignedValue))))
            {
                if (otherSideSet != null && previousValue != null /* && !reference.HasAssignedValue*/)
                {
                    reference.SetEntity(null);
                    otherSideSet(previousValue).Remove(this as TThisEntity);
                    if (idChangedAction != null)
                    {
                        previousValue.IdChanged -= idChangedAction;
                    }
                }

                bool loadReference = isLoaded && newValue != null && reference.HasLoadedValue == false && reference.HasAssignedValue == false;
                if (loadReference)
                {
                    for (int i = 0; i < referenceIdValue.Length; i++)
                    {
                        if (referenceIdValue[i] != newValueId[i])
                        {
                            loadReference = false;
                            break;
                        }
                    }

                    if (loadReference)
                    {
                        reference.Load(newValue);
                        if (newValue != null && newValue._lazyLoadChildren)
                        {
                            if (otherSideSet != null)
                            {
                                var otherSide = otherSideSet(newValue);
                                if (otherSide is DbEntitySet <TThisEntity> && ((DbEntitySet <TThisEntity>)otherSide).lazyLoadValues)
                                {
                                    otherSide.Add(this as TThisEntity);
                                }
                            }
                            else if (setOtherSideEntity != null)
                            {
                                setOtherSideEntity(newValue, (TThisEntity)this);
                            }
                        }
                    }
                }

                if (!loadReference)
                {
                    // Only update the referenceId if this entity was not loaded from the DB
                    // or when it is no primary key, or when the referenceId is set to null (i.e. the other item is going to be deleted)
                    // or the opposite: referenceId is currently null and is now set to another value
                    // added && referenceIsForeignKey because of illegal set action to null to parent entity (child was set to null)
                    if ((newValue == null && referenceIsForeignKey) ||
                        referenceIdValue[0] == null ||
                        (newValue != null && (!isLoaded || referenceIsForeignKey)))
                    {
                        for (int i = 0; i < referenceIdSetter.Length; i++)
                        {
                            // In order that IdChanged() or similar events are called, we assign the property instead of directly the referenceIdValue
                            // Set the id explicitly to 0 (zero), such that e.g. InvoicingId.HasValue returns true, so by looking at InvoicingId you know that Invoicoing was set to an instance
                            referenceIdSetter[i](newValue == null ? null : newValueId[i]);
                            // referenceIdSetter[i](newValue == null || newValueId[i] == 0 ? null : newValueId[i]);
                        }
                    }

                    if (newValue != null
                        &&
                        ((!reference.HasLoadedValue && !reference.HasAssignedValue) || reference.GetEntity(null) == null ||
                         ((ILongId)reference.GetEntity(null)).Id != ((ILongId)newValue).Id) ||
                        (newValue == null && reference.GetEntity(null) != null))
                    {
                        reference.SetEntity(newValue);
                        if (newValue != null)
                        {
                            if (otherSideSet != null)
                            {
                                var otherSide = otherSideSet(newValue);
                                if (otherSide is DbEntitySet <TThisEntity> && ((DbEntitySet <TThisEntity>)otherSide).lazyLoadValues &&
                                    (!isLoaded || previousValue != null || reference.HasAssignedValue))
                                {
                                    otherSide.Add(this as TThisEntity);
                                }
                            }
                            else if (setOtherSideEntity != null)
                            {
                                if (previousValue != null &&
                                    !referenceIsForeignKey &&
                                    !ReferenceEquals(previousValue, newValue) &&
                                    otherSideSet == null)
                                {
                                    setOtherSideEntity(previousValue, null);
                                }
                                setOtherSideEntity(newValue, (TThisEntity)this);
                            }

                            if (idChangedAction != null)
                            {
                                newValue.IdChanged += idChangedAction;
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 5
0
 public void ProcessAssociation(DbEntity parentEntity, IDbEntityRef dbEntityRef) => ProcessAssociation(parentEntity, (IDbEntityRefInternal)dbEntityRef);