public override object Next(StateEntry entry, IProperty property)
        {
            Check.NotNull(property, "property");

            Contract.Assert(property.IsForeignKey());

            var entityType = property.EntityType;
            var stateManager = entry.Configuration.StateManager;

            foreach (var foreignKey in entityType.ForeignKeys)
            {
                for (var propertyIndex = 0; propertyIndex < foreignKey.Properties.Count; propertyIndex++)
                {
                    if (property == foreignKey.Properties[propertyIndex])
                    {
                        foreach (var navigation in entityType.Navigations
                            .Concat(foreignKey.ReferencedEntityType.Navigations)
                            .Where(n => n.ForeignKey == foreignKey)
                            .Distinct())
                        {
                            var principal = TryFindPrincipal(stateManager, navigation, entry.Entity);

                            if (principal != null)
                            {
                                var principalEntry = stateManager.GetOrCreateEntry(principal);

                                return principalEntry[foreignKey.ReferencedProperties[propertyIndex]];
                            }
                        }
                    }
                }
            }

            return null;
        }
        public override object Next(StateEntry entry, IProperty property)
        {
            Check.NotNull(entry, "entry");
            Check.NotNull(property, "property");

            return Convert.ChangeType(Interlocked.Increment(ref _current), property.PropertyType);
        }
        public virtual async Task<object> NextAsync(StateEntry stateEntry, IProperty property, CancellationToken cancellationToken = default(CancellationToken))
        {
            Check.NotNull(stateEntry, "stateEntry");
            Check.NotNull(property, "property");

            var newValue = GetNextValue();

            // If the chosen value is outside of the current block then we need a new block.
            // It is possible that other threads will use all of the new block before this thread
            // gets a chance to use the new new value, so use a while here to do it all again.
            while (newValue.Current >= newValue.Max)
            {
                // Once inside the lock check to see if another thread already got a new block, in which
                // case just get a value out of the new block instead of requesting one.
                using (await _lock.LockAsync(cancellationToken))
                {
                    if (newValue.Max == _currentValue.Max)
                    {
                        var commandInfo = PrepareCommand(stateEntry.Configuration);

                        var newCurrent = (long)await _executor.ExecuteScalarAsync(commandInfo.Item1.DbConnection, commandInfo.Item1.DbTransaction, commandInfo.Item2, cancellationToken).ConfigureAwait(false);
                        newValue = new SequenceValue(newCurrent, newCurrent + _blockSize);
                        _currentValue = newValue;
                    }
                    else
                    {
                        newValue = GetNextValue();
                    }
                }
            }

            return Convert.ChangeType(newValue.Current, property.PropertyType);
        }
        public override object Next(StateEntry entry, IProperty property)
        {
            Check.NotNull(entry, "entry");
            Check.NotNull(property, "property");

            return Guid.NewGuid();
        }
示例#5
0
        private void ForeignKeyPropertyChangedAction(StateEntry entry, IProperty property, object oldValue, object newValue)
        {
            var stateManager = _configuration.StateManager;

            foreach (var foreignKey in entry.EntityType.ForeignKeys.Where(p => p.Properties.Contains(property)).Distinct())
            {
                var navigations = stateManager.Model.GetNavigations(foreignKey).ToArray();

                var oldPrincipalEntry = stateManager.GetPrincipal(entry.RelationshipsSnapshot, foreignKey);
                if (oldPrincipalEntry != null)
                {
                    Unfixup(navigations, oldPrincipalEntry, entry);
                }

                var principalEntry = stateManager.GetPrincipal(entry, foreignKey);
                if (principalEntry != null)
                {
                    if (foreignKey.IsUnique)
                    {
                        var oldDependents = stateManager.GetDependents(principalEntry, foreignKey).Where(e => e != entry).ToArray();

                        // TODO: Decide how to handle case where multiple values found (negative case)
                        if (oldDependents.Length > 0)
                        {
                            StealReference(foreignKey, oldDependents[0]);
                        }
                    }

                    DoFixup(navigations, principalEntry, new[] { entry });
                }
            }
        }
示例#6
0
        public virtual void ForeignKeyPropertyChanged(StateEntry entry, IProperty property, object oldValue, object newValue)
        {
            Check.NotNull(entry, "entry");
            Check.NotNull(property, "property");

            PerformFixup(() => ForeignKeyPropertyChangedAction(entry, property, oldValue, newValue));
        }
        private static IEnumerable<IPropertyBase> GetProperties(StateEntry stateEntry)
        {
            var entityType = stateEntry.EntityType;

            return entityType.GetKey().Properties.Concat(
                entityType.ForeignKeys.SelectMany(fk => fk.Properties)).Distinct()
                .Concat<IPropertyBase>(entityType.Navigations);
        }
示例#8
0
        public PropertyEntry([NotNull] StateEntry stateEntry, [NotNull] string name)
        {
            Check.NotNull(stateEntry, "stateEntry");
            Check.NotEmpty(name, "name");

            _stateEntry = stateEntry;
            _property = stateEntry.EntityType.GetProperty(name);
        }
        public virtual Task<object> NextAsync(
            StateEntry stateEntry,
            IProperty property,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            Check.NotNull(stateEntry, "stateEntry");
            Check.NotNull(property, "property");

            return Task.FromResult(Next(stateEntry, property));
        }
        private Func<StateEntry, ITableEntity> GetOrMakeAdapter(StateEntry entry)
        {
            return _instanceCreatorCache.GetOrAdd(entry, e =>
                {
                    var paramExpression = new[]
                        {
                            Expression.Parameter(typeof(StateEntry), "entry")
                        };
                    var ctorExpression = Expression.New(
                        typeof(StateEntryTableEntityAdapter<>)
                            .MakeGenericType(e.Entity.GetType())
                            .GetConstructor(new[] { typeof(StateEntry) }),
                        paramExpression
                        );

                    var lambda = Expression.Lambda<Func<StateEntry, ITableEntity>>(ctorExpression, paramExpression);
                    return lambda.Compile();
                });
        }
示例#11
0
        private bool DetectForeignKeyChange(StateEntry entry, IProperty property)
        {
            if (property.IsForeignKey())
            {
                var snapshotValue = entry.RelationshipsSnapshot[property];
                var currentValue  = entry[property];

                // Note that mutation of a byte[] key is not supported or detected, but two different instances
                // of byte[] with the same content must be detected as equal.
                if (!StructuralComparisons.StructuralEqualityComparer.Equals(currentValue, snapshotValue))
                {
                    entry.StateManager.Notify.ForeignKeyPropertyChanged(entry, property, snapshotValue, currentValue);

                    return(true);
                }
            }

            return(false);
        }
示例#12
0
        private void DetectKeyChange(StateEntry entry, IProperty property, Sidecar snapshot)
        {
            if (!snapshot.HasValue(property))
            {
                return;
            }

            // TODO: Perf: make it fast to check if a property is part of any key
            var isPrimaryKey   = property.IsPrimaryKey();
            var isPrincipalKey = _model.Service.GetReferencingForeignKeys(property).Any();
            var isForeignKey   = property.IsForeignKey();

            if (isPrimaryKey ||
                isPrincipalKey ||
                isForeignKey)
            {
                var snapshotValue = snapshot[property];
                var currentValue  = entry[property];

                // Note that mutation of a byte[] key is not supported or detected, but two different instances
                // of byte[] with the same content must be detected as equal.
                if (!StructuralComparisons.StructuralEqualityComparer.Equals(currentValue, snapshotValue))
                {
                    if (isForeignKey)
                    {
                        entry.StateManager.Notify.ForeignKeyPropertyChanged(entry, property, snapshotValue, currentValue);
                    }

                    if (isPrimaryKey)
                    {
                        entry.StateManager.UpdateIdentityMap(entry, snapshot.GetPrimaryKeyValue());
                    }

                    if (isPrincipalKey)
                    {
                        entry.StateManager.Notify.PrincipalKeyPropertyChanged(entry, property, snapshotValue, currentValue);
                    }

                    snapshot.TakeSnapshot(property);
                }
            }
        }
示例#13
0
        public virtual void ForeignKeyPropertyChanged(StateEntry entry, IProperty property, object oldValue, object newValue)
        {
            Check.NotNull(entry, "entry");
            Check.NotNull(property, "property");

            foreach (var foreignKey in entry.EntityType.ForeignKeys.Where(p => p.Properties.Contains(property)).Distinct())
            {
                var oldPrincipalEntry = _stateManager.GetPrincipal(entry, foreignKey, useForeignKeySnapshot: true);
                if (oldPrincipalEntry != null)
                {
                    UndoFixup(foreignKey, oldPrincipalEntry, entry);
                }

                var principalEntry = _stateManager.GetPrincipal(entry, foreignKey, useForeignKeySnapshot: false);
                if (principalEntry != null)
                {
                    DoFixup(foreignKey, principalEntry, new[] { entry });
                }
            }
        }
示例#14
0
        private void PrincipalKeyPropertyChangedAction(StateEntry entry, IProperty property, object oldValue, object newValue)
        {
            foreach (var foreignKey in _model.Service.EntityTypes.SelectMany(
                         e => e.ForeignKeys.Where(f => f.ReferencedProperties.Contains(property))))
            {
                var newKeyValues = foreignKey.ReferencedProperties.Select(p => entry[p]).ToList();
                var oldKey       = entry.RelationshipsSnapshot.GetPrincipalKeyValue(foreignKey);

                foreach (var dependent in entry.StateManager.StateEntries.Where(
                             e => e.EntityType == foreignKey.EntityType &&
                             oldKey.Equals(e.GetDependentKeyValue(foreignKey))).ToList())
                {
                    if (dependent.TryGetSidecar(Sidecar.WellKnownNames.StoreGeneratedValues) == null)
                    {
                        dependent.AddSidecar(_storeGeneratedValuesFactory.Create(dependent));
                    }
                    SetForeignKeyValue(dependent, foreignKey.Properties, newKeyValues);
                }
            }
        }
示例#15
0
        public virtual StateEntry GetPrincipal([NotNull] StateEntry dependentEntry, [NotNull] IForeignKey foreignKey)
        {
            Check.NotNull(dependentEntry, "dependentEntry");
            Check.NotNull(foreignKey, "foreignKey");

            var dependentKeyValue = dependentEntry.GetDependentKeyValue(foreignKey);

            // TODO: Add additional indexes so that this isn't a linear lookup
            var principals = StateEntries.Where(
                e => e.EntityType == foreignKey.ReferencedEntityType &&
                dependentKeyValue.Equals(e.GetPrincipalKeyValue(foreignKey))).ToArray();

            if (principals.Length > 1)
            {
                // TODO: Better exception message
                throw new InvalidOperationException("Multiple matching principals.");
            }

            return(principals.FirstOrDefault());
        }
示例#16
0
        public virtual void StartTracking([NotNull] StateEntry entry)
        {
            Check.NotNull(entry, "entry");

            var entityType = entry.EntityType;

            if (entry.Configuration.Services.StateManager != this)
            {
                throw new InvalidOperationException(Strings.FormatWrongStateManager(entityType.Name));
            }

            StateEntry existingEntry;

            if (entry.Entity != null)
            {
                if (!_entityReferenceMap.TryGetValue(entry.Entity, out existingEntry))
                {
                    _entityReferenceMap[entry.Entity] = entry;
                }
                else if (existingEntry != entry)
                {
                    throw new InvalidOperationException(Strings.FormatMultipleStateEntries(entityType.Name));
                }
            }

            var keyValue = CreateKey(entityType, entityType.GetKey().Properties, entry);

            if (_identityMap.TryGetValue(keyValue, out existingEntry))
            {
                if (existingEntry != entry)
                {
                    // TODO: Consider a hook for identity resolution
                    // TODO: Consider specialized exception types
                    throw new InvalidOperationException(Strings.FormatIdentityConflict(entityType.Name));
                }
            }
            else
            {
                _identityMap[keyValue] = entry;
            }
        }
示例#17
0
        public virtual void SidecarPropertyChanged(StateEntry entry, IPropertyBase propertyBase)
        {
            Check.NotNull(entry, "entry");
            Check.NotNull(propertyBase, "propertyBase");

            var property = propertyBase as IProperty;

            if (property == null)
            {
                return;
            }

            var snapshot = entry.TryGetSidecar(Sidecar.WellKnownNames.RelationshipsSnapshot);

            if (snapshot == null)
            {
                return;
            }

            DetectKeyChange(entry, property, snapshot);
        }
示例#18
0
        public virtual void StopTracking([NotNull] StateEntry entry)
        {
            Check.NotNull(entry, "entry");

            if (entry.Entity != null)
            {
                _entityReferenceMap.Remove(entry.Entity);
            }

            var entityType = entry.EntityType;

            var keyValue = CreateKey(entityType, entityType.GetKey().Properties, entry);

            StateEntry existingEntry;

            if (_identityMap.TryGetValue(keyValue, out existingEntry) &&
                existingEntry == entry)
            {
                _identityMap.Remove(keyValue);
            }
        }
示例#19
0
        private void ConditionallyClearInverse(StateEntry entry, INavigation navigation, object entity)
        {
            var inverse = navigation.TryGetInverse();

            if (inverse != null)
            {
                if (inverse.IsCollection())
                {
                    _collectionAccessorSource.GetAccessor(inverse).Remove(entity, entry.Entity);
                }
                else
                {
                    if (ReferenceEquals(_getterSource.GetAccessor(inverse).GetClrValue(entity), entry.Entity))
                    {
                        _setterSource.GetAccessor(inverse).SetClrValue(entity, null);
                    }
                }

                entry.StateManager.GetOrCreateEntry(entity).RelationshipsSnapshot.TakeSnapshot(inverse);
            }
        }
示例#20
0
        private void StealReference(IForeignKey foreignKey, StateEntry dependentEntry)
        {
            foreach (var navigation in dependentEntry.EntityType.Navigations.Where(n => n.ForeignKey == foreignKey))
            {
                if (navigation.PointsToPrincipal)
                {
                    _setterSource.GetAccessor(navigation).SetClrValue(dependentEntry.Entity, null);
                    dependentEntry.RelationshipsSnapshot.TakeSnapshot(navigation);
                }
            }

            var nullableProperties = foreignKey.Properties.Where(p => p.IsNullable).ToList();

            if (nullableProperties.Count > 0)
            {
                foreach (var property in nullableProperties)
                {
                    dependentEntry[property] = null;
                }
            }
        }
示例#21
0
        public virtual StateEntry SnapshotAndSubscribe([NotNull] StateEntry entry)
        {
            var entityType = entry.EntityType;

            if (!entityType.UseLazyOriginalValues)
            {
                entry.OriginalValues.TakeSnapshot();
                entry.RelationshipsSnapshot.TakeSnapshot();
            }

            var changing = entry.Entity as INotifyPropertyChanging;

            if (changing != null)
            {
                changing.PropertyChanging += (s, e) =>
                {
                    var property = TryGetPropertyBase(entityType, e.PropertyName);
                    if (property != null)
                    {
                        _notifier.PropertyChanging(entry, property);
                    }
                };
            }

            var changed = entry.Entity as INotifyPropertyChanged;

            if (changed != null)
            {
                changed.PropertyChanged += (s, e) =>
                {
                    var property = TryGetPropertyBase(entityType, e.PropertyName);
                    if (property != null)
                    {
                        _notifier.PropertyChanged(entry, property);
                    }
                };
            }

            return(entry);
        }
示例#22
0
        private void NavigationCollectionChangedAction(
            StateEntry entry, INavigation navigation, IEnumerable <object> added, IEnumerable <object> removed)
        {
            Debug.Assert(navigation.IsCollection());

            var dependentProperties = navigation.ForeignKey.Properties;
            var principalValues     = navigation.ForeignKey.ReferencedProperties.Select(p => entry[p]).ToList();

            // TODO: What if the entity is not yet being tracked?
            // Issue #323
            foreach (var entity in removed)
            {
                ConditionallySetNullForeignKey(entry.StateManager.GetOrCreateEntry(entity), dependentProperties, principalValues);
                ConditionallyClearInverse(entry, navigation, entity);
            }

            foreach (var entity in added)
            {
                SetForeignKeyValue(entry.StateManager.GetOrCreateEntry(entity), dependentProperties, principalValues);
                SetInverse(entry, navigation, entity);
            }
        }
示例#23
0
        public virtual void PrincipalKeyPropertyChanged(StateEntry entry, IProperty property, object oldValue, object newValue)
        {
            Check.NotNull(entry, "entry");
            Check.NotNull(property, "property");

            // We don't prevent recursive entry here because changed of principal key can have cascading effects
            // when principal key is also foreign key.

            foreach (var foreignKey in _model.Service.EntityTypes.SelectMany(
                         e => e.ForeignKeys.Where(f => f.ReferencedProperties.Contains(property))))
            {
                var newKeyValues = foreignKey.ReferencedProperties.Select(p => entry[p]).ToList();
                var oldKey       = entry.RelationshipsSnapshot.GetPrincipalKeyValue(foreignKey);

                foreach (var dependent in entry.StateManager.StateEntries.Where(
                             e => e.EntityType == foreignKey.EntityType &&
                             oldKey.Equals(e.GetDependentKeyValue(foreignKey))).ToList())
                {
                    SetForeignKeyValue(foreignKey, dependent, newKeyValues);
                }
            }
        }
        public virtual StateEntry SnapshotAndSubscribe([NotNull] StateEntry entry)
        {
            if (!entry.EntityType.UseLazyOriginalValues)
            {
                entry.OriginalValues.TakeSnapshot();
                entry.ForeignKeysSnapshot.TakeSnapshot();
            }

            var changing = entry.Entity as INotifyPropertyChanging;

            if (changing != null)
            {
                changing.PropertyChanging += (s, e) =>
                {
                    var property = entry.EntityType.TryGetProperty(e.PropertyName);
                    if (property != null)
                    {
                        entry.PropertyChanging(property);
                    }
                };
            }

            var changed = entry.Entity as INotifyPropertyChanged;

            if (changed != null)
            {
                changed.PropertyChanged += (s, e) =>
                {
                    var property = entry.EntityType.TryGetProperty(e.PropertyName);
                    if (property != null)
                    {
                        entry.PropertyChanged(property);
                    }
                };
            }

            return(entry);
        }
示例#25
0
        private void DoFixup(IEnumerable <INavigation> navigations, StateEntry principalEntry, StateEntry[] dependentEntries)
        {
            foreach (var navigation in navigations)
            {
                if (navigation.PointsToPrincipal)
                {
                    var setter = _setterSource.GetAccessor(navigation);

                    foreach (var dependent in dependentEntries)
                    {
                        setter.SetClrValue(dependent.Entity, principalEntry.Entity);
                        dependent.RelationshipsSnapshot.TakeSnapshot(navigation);
                    }
                }
                else
                {
                    if (navigation.IsCollection())
                    {
                        var collectionAccessor = _collectionAccessorSource.GetAccessor(navigation);

                        foreach (var dependent in dependentEntries)
                        {
                            if (!collectionAccessor.Contains(principalEntry.Entity, dependent.Entity))
                            {
                                collectionAccessor.Add(principalEntry.Entity, dependent.Entity);
                            }
                        }
                    }
                    else
                    {
                        // TODO: Decide how to handle case where multiple values match non-collection nav prop
                        // Issue #739
                        _setterSource.GetAccessor(navigation).SetClrValue(principalEntry.Entity, dependentEntries.Single().Entity);
                    }
                    principalEntry.RelationshipsSnapshot.TakeSnapshot(navigation);
                }
            }
        }
示例#26
0
        private void SetInverse(StateEntry entry, INavigation navigation, object entity)
        {
            var inverse = navigation.TryGetInverse();

            if (inverse != null)
            {
                if (inverse.IsCollection())
                {
                    var collectionAccessor = _collectionAccessorSource.GetAccessor(inverse);

                    if (!collectionAccessor.Contains(entity, entry.Entity))
                    {
                        collectionAccessor.Add(entity, entry.Entity);
                    }
                }
                else
                {
                    _setterSource.GetAccessor(inverse).SetClrValue(entity, entry.Entity);
                }

                entry.StateManager.GetOrCreateEntry(entity).RelationshipsSnapshot.TakeSnapshot(inverse);
            }
        }
示例#27
0
 private void Unfixup(INavigation navigation, StateEntry oldPrincipalEntry, StateEntry dependentEntry)
 {
     if (navigation.PointsToPrincipal)
     {
         _setterSource.GetAccessor(navigation).SetClrValue(dependentEntry.Entity, null);
         dependentEntry.RelationshipsSnapshot.TakeSnapshot(navigation);
     }
     else
     {
         if (navigation.IsCollection())
         {
             var collectionAccessor = _collectionAccessorSource.GetAccessor(navigation);
             if (collectionAccessor.Contains(oldPrincipalEntry.Entity, dependentEntry.Entity))
             {
                 collectionAccessor.Remove(oldPrincipalEntry.Entity, dependentEntry.Entity);
             }
         }
         else
         {
             _setterSource.GetAccessor(navigation).SetClrValue(oldPrincipalEntry.Entity, null);
         }
     }
 }
        public ColumnModification(
            [NotNull] StateEntry stateEntry,
            [NotNull] IProperty property,
            [CanBeNull] string parameterName,
            [CanBeNull] string originalParameterName,
            bool isRead,
            bool isWrite,
            bool isKey,
            bool isCondition)
        {
            Check.NotNull(stateEntry, "stateEntry");
            Check.NotNull(property, "property");

            _stateEntry = stateEntry;
            _property = property;
            _columnName = property.ColumnName();
            _parameterName = parameterName;
            _originalParameterName = originalParameterName;
            _isRead = isRead;
            _isWrite = isWrite;
            _isKey = isKey;
            _isCondition = isCondition;
        }
示例#29
0
        public virtual void PropertyChanging(StateEntry entry, IPropertyBase propertyBase)
        {
            Check.NotNull(entry, "entry");
            Check.NotNull(propertyBase, "propertyBase");

            if (!entry.EntityType.UseEagerSnapshots)
            {
                var property = propertyBase as IProperty;
                if (property != null &&
                    property.OriginalValueIndex >= 0)
                {
                    entry.OriginalValues.EnsureSnapshot(property);
                }

                var navigation = propertyBase as INavigation;
                if ((navigation != null && !navigation.IsCollection()) ||
                    (property != null && (property.IsKey() || property.IsForeignKey())))
                {
                    // TODO: Consider making snapshot temporary here since it is no longer required after PropertyChanged is called
                    // See issue #730
                    entry.RelationshipsSnapshot.TakeSnapshot(propertyBase);
                }
            }
        }
        public override object Next(StateEntry entry, IProperty property)
        {
            Check.NotNull(entry, "entry");
            Check.NotNull(property, "property");

            var guidBytes = Guid.NewGuid().ToByteArray();
            var counterBytes = BitConverter.GetBytes(Interlocked.Increment(ref _counter));

            if (!BitConverter.IsLittleEndian)
            {
                Array.Reverse(counterBytes);
            }

            guidBytes[08] = counterBytes[1];
            guidBytes[09] = counterBytes[0];
            guidBytes[10] = counterBytes[7];
            guidBytes[11] = counterBytes[6];
            guidBytes[12] = counterBytes[5];
            guidBytes[13] = counterBytes[4];
            guidBytes[14] = counterBytes[3];
            guidBytes[15] = counterBytes[2];

            return new Guid(guidBytes);
        }
示例#31
0
 public void PrincipalKeyPropertyChanged(StateEntry entry, IProperty property, object oldValue, object newValue)
 {
 }
示例#32
0
 public void NavigationReferenceChanged(StateEntry entry, INavigation navigation, object oldValue, object newValue)
 {
 }
示例#33
0
 public void StateChanged(StateEntry entry, EntityState oldState)
 {
 }
示例#34
0
        public virtual Sidecar CreateRelationshipSnapshot([NotNull] StateEntry stateEntry)
        {
            Check.NotNull(stateEntry, "stateEntry");

            return(_relationshipsSnapshotFactory.Create(stateEntry));
        }
示例#35
0
 private static void ConditionallySetNullForeignKey(
     StateEntry dependentEntry, IReadOnlyList<IProperty> dependentProperties,
     StateEntry principalEntry, IReadOnlyList<IProperty> principalProperties)
 {
     ConditionallySetNullForeignKey(dependentEntry, dependentProperties, principalProperties.Select(p => principalEntry[p]).ToArray());
 }
 protected override Sidecar CreateSidecar(StateEntry entry = null)
 {
     return new StoreGeneratedValuesFactory().Create(entry ?? CreateStateEntry());
 }
示例#37
0
 private static void ConditionallySetNullForeignKey(
     StateEntry dependentEntry, IReadOnlyList<IProperty> dependentProperties, IReadOnlyList<object> principalValues)
 {
     // Don't null out the FK if it has already be set to point to a different principal
     if (dependentProperties.Select(p => dependentEntry[p]).StructuralSequenceEqual(principalValues))
     {
         SetNullForeignKey(dependentEntry, dependentProperties);
     }
 }
示例#38
0
        public virtual void NavigationReferenceChanged(StateEntry entry, INavigation navigation, object oldValue, object newValue)
        {
            Check.NotNull(entry, "entry");
            Check.NotNull(navigation, "navigation");

            PerformFixup(() => NavigationReferenceChangedAction(entry, navigation, oldValue, newValue));
        }
示例#39
0
 protected ArraySidecar([NotNull] StateEntry stateEntry, int count)
     : base(stateEntry)
 {
     _values = new object[count];
 }
示例#40
0
        public EntityEntry([NotNull] StateEntry stateEntry)
        {
            Check.NotNull(stateEntry, "stateEntry");

            _stateEntry = stateEntry;
        }
示例#41
0
        private void NavigationReferenceChangedAction(StateEntry entry, INavigation navigation, object oldValue, object newValue)
        {
            var foreignKey = navigation.ForeignKey;
            var dependentProperties = foreignKey.Properties;
            var principalProperties = foreignKey.ReferencedProperties;
            var stateManager = _configuration.StateManager;

            // TODO: What if the other entry is not yet being tracked?

            if (navigation.PointsToPrincipal)
            {
                if (newValue != null)
                {
                    SetForeignKeyValue(entry, dependentProperties, stateManager.GetOrCreateEntry(newValue), principalProperties);
                }
                else
                {
                    SetNullForeignKey(entry, dependentProperties);
                }
            }
            else
            {
                Contract.Assert(foreignKey.IsUnique);

                if (newValue != null)
                {
                    SetForeignKeyValue(stateManager.GetOrCreateEntry(newValue), dependentProperties, entry, principalProperties);
                }

                if (oldValue != null)
                {
                    ConditionallySetNullForeignKey(stateManager.GetOrCreateEntry(oldValue), dependentProperties, entry, principalProperties);
                }
            }

            if (oldValue != null)
            {
                ConditionallyClearInverse(entry, navigation, oldValue);
            }

            if (newValue != null)
            {
                SetInverse(entry, navigation, newValue);
            }
        }
 private Sidecar CreateSidecar(StateEntry entry = null)
 {
     return new RelationshipsSnapshotFactory().Create(entry ?? CreateStateEntry());
 }
示例#43
0
 public OriginalValues([NotNull] StateEntry stateEntry)
     : base(stateEntry, Check.NotNull(stateEntry, "stateEntry").EntityType.OriginalValueCount)
 {
 }
示例#44
0
        private void InitialFixup(StateEntry entry, EntityState oldState)
        {
            var entityType = entry.EntityType;

            foreach (var navigation in entityType.Navigations)
            {
                var navigationValue = entry[navigation];

                if (navigationValue != null)
                {
                    if (navigation.IsCollection())
                    {
                        NavigationCollectionChangedAction(
                            entry,
                            navigation,
                            ((IEnumerable)navigationValue).Cast <object>().ToList(),
                            Enumerable.Empty <object>());
                    }
                    else
                    {
                        NavigationReferenceChangedAction(
                            entry,
                            navigation,
                            null,
                            navigationValue);
                    }
                }
            }

            var stateEntries = entry.StateManager.StateEntries.ToList();

            // TODO: Perf on this state manager query
            foreach (var navigation in _model.Service.EntityTypes
                     .SelectMany(e => e.Navigations)
                     .Where(n => n.GetTargetType() == entityType))
            {
                IClrCollectionAccessor collectionAccessor = null;
                if (navigation.IsCollection())
                {
                    collectionAccessor = _collectionAccessorSource.GetAccessor(navigation);
                }

                var navigationEntityType = navigation.EntityType;

                foreach (var relatedEntry in stateEntries)
                {
                    if (relatedEntry.EntityType != navigationEntityType ||
                        relatedEntry == entry)
                    {
                        continue;
                    }

                    if (collectionAccessor != null)
                    {
                        if (collectionAccessor.Contains(relatedEntry.Entity, entry.Entity))
                        {
                            NavigationCollectionChangedAction(
                                relatedEntry,
                                navigation,
                                new[] { entry.Entity },
                                Enumerable.Empty <object>());
                        }
                    }
                    else
                    {
                        var navigationValue = relatedEntry[navigation];

                        if (navigationValue != null)
                        {
                            if (ReferenceEquals(navigationValue, entry.Entity))
                            {
                                NavigationReferenceChangedAction(
                                    relatedEntry,
                                    navigation,
                                    null,
                                    navigationValue);
                            }
                        }
                    }
                }
            }

            foreach (var foreignKey in entityType.ForeignKeys)
            {
                var principalEntry = entry.StateManager.GetPrincipal(entry.RelationshipsSnapshot, foreignKey);
                if (principalEntry != null)
                {
                    DoFixup(foreignKey, principalEntry, new[] { entry });
                }
            }

            foreach (var foreignKey in _model.Service.GetReferencingForeignKeys(entityType))
            {
                var dependents = entry.StateManager.GetDependents(entry, foreignKey).ToArray();

                if (dependents.Length > 0)
                {
                    DoFixup(foreignKey, entry, dependents);
                }
            }
        }
示例#45
0
 private EntityKey CreateKey(IEntityType entityType, IReadOnlyList <IProperty> properties, StateEntry entry)
 {
     return(_keyFactorySource.GetKeyFactory(properties).Create(entityType, properties, entry));
 }
示例#46
0
 private void DoFixup(IForeignKey foreignKey, StateEntry principalEntry, StateEntry[] dependentEntries)
 {
     DoFixup(_model.Service.GetNavigations(foreignKey).ToList(), principalEntry, dependentEntries);
 }
        public override EntityKey Create(IEntityType entityType, IReadOnlyList <IProperty> properties, StateEntry entry)
        {
            Check.NotNull(entityType, "entityType");
            Check.NotNull(properties, "properties");
            Check.NotNull(entry, "entry");

            // TODO: What happens if we get a null property value?
            return(new SimpleEntityKey <TKey>(entityType, (TKey)entry[properties[0]]));
        }
示例#48
0
        private void ConditionallyClearInverse(StateEntry entry, INavigation navigation, object entity)
        {
            var inverse = navigation.TryGetInverse();

            if (inverse != null)
            {
                if (inverse.IsCollection())
                {
                    _collectionAccessorSource.GetAccessor(inverse).Remove(entity, entry.Entity);
                }
                else
                {
                    if (ReferenceEquals(_getterSource.GetAccessor(inverse).GetClrValue(entity), entry.Entity))
                    {
                        _setterSource.GetAccessor(inverse).SetClrValue(entity, null);
                    }
                }

                _configuration.StateManager.GetOrCreateEntry(entity).RelationshipsSnapshot.TakeSnapshot(inverse);
            }
        }
示例#49
0
        public virtual Sidecar CreateOriginalValues([NotNull] StateEntry stateEntry)
        {
            Check.NotNull(stateEntry, "stateEntry");

            return(_originalValuesFactory.Create(stateEntry));
        }
示例#50
0
 private void Unfixup(IEnumerable <INavigation> navigations, StateEntry oldPrincipalEntry, StateEntry dependentEntry)
 {
     foreach (var navigation in navigations)
     {
         Unfixup(navigation, oldPrincipalEntry, dependentEntry);
         oldPrincipalEntry.RelationshipsSnapshot.TakeSnapshot(navigation);
     }
 }
示例#51
0
 public void StateChanging(StateEntry entry, EntityState newState)
 {
 }
示例#52
0
        private void SetInverse(StateEntry entry, INavigation navigation, object entity)
        {
            var inverse = navigation.TryGetInverse();

            if (inverse != null)
            {
                if (inverse.IsCollection())
                {
                    var collectionAccessor = _collectionAccessorSource.GetAccessor(inverse);

                    if (!collectionAccessor.Contains(entity, entry.Entity))
                    {
                        collectionAccessor.Add(entity, entry.Entity);
                    }
                }
                else
                {
                    _setterSource.GetAccessor(inverse).SetClrValue(entity, entry.Entity);
                }

                _configuration.StateManager.GetOrCreateEntry(entity).RelationshipsSnapshot.TakeSnapshot(inverse);
            }
        }
示例#53
0
 public void ForeignKeyPropertyChanged(StateEntry entry, IProperty property, object oldValue, object newValue)
 {
 }
示例#54
0
 private static void ConditionallySetNullForeignKey(
     StateEntry dependentEntry, IReadOnlyList <IProperty> dependentProperties,
     StateEntry principalEntry, IReadOnlyList <IProperty> principalProperties)
 {
     ConditionallySetNullForeignKey(dependentEntry, dependentProperties, principalProperties.Select(p => principalEntry[p]).ToList());
 }
示例#55
0
 public virtual void NavigationCollectionChanged(StateEntry entry, INavigation navigation, ISet<object> added, ISet<object> removed)
 {
 }
示例#56
0
 private static void SetNullForeignKey(StateEntry dependentEntry, IReadOnlyList<IProperty> dependentProperties)
 {
     foreach (var dependentProperty in dependentProperties)
     {
         // TODO: Conceptual nulls
         dependentEntry[dependentProperty] = null;
         dependentEntry.RelationshipsSnapshot.TakeSnapshot(dependentProperty);
     }
 }
示例#57
0
 public virtual void StateChanging(StateEntry entry, EntityState newState)
 {
 }
示例#58
0
        protected Sidecar([NotNull] StateEntry stateEntry)
        {
            Check.NotNull(stateEntry, "stateEntry");

            _stateEntry = stateEntry;
        }
 public RelationshipsSnapshot([NotNull] StateEntry stateEntry)
     : base(stateEntry, GetProperties(Check.NotNull(stateEntry, "stateEntry")))
 {
 }
 protected override Sidecar CreateSidecar(StateEntry entry = null)
 {
     return new OriginalValuesFactory().Create(entry ?? CreateStateEntry());
 }