示例#1
0
        private void OnEntityCreatedHandler(EntityCreatedEventArgs args)
        {
            if (!LinqToDBForEFTools.EnableChangeTracker ||
                !Tracking ||
                Context !.ChangeTracker.QueryTrackingBehavior == QueryTrackingBehavior.NoTracking)
            {
                return;
            }

            var type = args.Entity.GetType();

            if (_lastType != type)
            {
                _lastType       = type;
                _lastEntityType = Context.Model.FindEntityType(type);
            }

            if (_lastEntityType == null)
            {
                return;
            }

            if (_stateManager == null)
            {
                _stateManager = Context.GetService <IStateManager>();
            }


            // It is a real pain to register entity in change tracker
            //
            InternalEntityEntry?entry = null;

            foreach (var key in _lastEntityType.GetKeys())
            {
                //TODO: Find faster way
                var keyArray = key.Properties.Where(p => p.PropertyInfo != null || p.FieldInfo != null).Select(p =>
                                                                                                               p.PropertyInfo != null
                                                ? p.PropertyInfo.GetValue(args.Entity)
                                                : p.FieldInfo.GetValue(args.Entity)).ToArray();

                if (keyArray.Length == key.Properties.Count)
                {
                    entry = _stateManager.TryGetEntry(key, keyArray);

                    if (entry != null)
                    {
                        break;
                    }
                }
            }

            if (entry == null)
            {
                entry = _stateManager.StartTrackingFromQuery(_lastEntityType, args.Entity, ValueBuffer.Empty);
            }

            args.Entity = entry.Entity;
        }
示例#2
0
 public EntityEntryGraphNode(
     InternalEntityEntry entry,
     TState?state,
     InternalEntityEntry?sourceEntry,
     INavigationBase?inboundNavigation)
     : base(entry, sourceEntry, inboundNavigation)
 {
     NodeState = state;
 }
 public EntityEntryGraphNode(
     InternalEntityEntry entry,
     InternalEntityEntry?sourceEntry,
     INavigationBase?inboundNavigation)
 {
     _entry            = entry;
     _sourceEntry      = sourceEntry;
     InboundNavigation = inboundNavigation;
 }
示例#4
0
 public EntityEntryGraphNode(
     [NotNull] InternalEntityEntry entry,
     [CanBeNull] TState?state,
     [CanBeNull] InternalEntityEntry?sourceEntry,
     [CanBeNull] INavigationBase?inboundNavigation)
     : base(entry, sourceEntry, inboundNavigation)
 {
     NodeState = state;
 }
示例#5
0
        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        public virtual bool TryGet(
            object entity,
            IEntityType?entityType,
            [NotNullWhen(true)] out InternalEntityEntry?entry,
            bool throwOnNonUniqueness)
        {
            entry = null;
            var found = _unchangedReferenceMap?.TryGetValue(entity, out entry) == true ||
                        _modifiedReferenceMap?.TryGetValue(entity, out entry) == true ||
                        _addedReferenceMap?.TryGetValue(entity, out entry) == true ||
                        _deletedReferenceMap?.TryGetValue(entity, out entry) == true ||
                        _detachedReferenceMap?.TryGetValue(entity, out entry) == true;

            if (!found &&
                _hasSubMap &&
                _sharedTypeReferenceMap != null)
            {
                if (entityType != null)
                {
                    if (_sharedTypeReferenceMap.TryGetValue(entityType, out var subMap))
                    {
                        return(subMap.TryGet(entity, entityType, out entry, throwOnNonUniqueness));
                    }
                }
                else
                {
                    var type = entity.GetType();
                    foreach (var keyValue in _sharedTypeReferenceMap)
                    {
                        // ReSharper disable once CheckForReferenceEqualityInstead.2
                        if (keyValue.Key.ClrType.IsAssignableFrom(type) &&
                            keyValue.Value.TryGet(entity, entityType, out var foundEntry, throwOnNonUniqueness))
                        {
                            if (found)
                            {
                                if (!throwOnNonUniqueness)
                                {
                                    entry = null;
                                    return(false);
                                }

                                throw new InvalidOperationException(
                                          CoreStrings.AmbiguousDependentEntity(
                                              entity.GetType().ShortDisplayName(),
                                              "." + nameof(EntityEntry.Reference) + "()." + nameof(ReferenceEntry.TargetEntry)));
                            }

                            entry = foundEntry;
                            found = true;
                        }
                    }
                }
            }

            return(found);
        }
示例#6
0
    private static InternalEntityEntry?TryPropagateValue(InternalEntityEntry entry, IProperty property, IProperty?generationProperty)
    {
        var entityType   = entry.EntityType;
        var stateManager = entry.StateManager;

        foreach (var foreignKey in entityType.GetForeignKeys())
        {
            for (var propertyIndex = 0; propertyIndex < foreignKey.Properties.Count; propertyIndex++)
            {
                if (property == foreignKey.Properties[propertyIndex])
                {
                    var principal = foreignKey.DependentToPrincipal == null
                        ? null
                        : entry[foreignKey.DependentToPrincipal];
                    InternalEntityEntry?principalEntry = null;
                    if (principal != null)
                    {
                        principalEntry = stateManager.GetOrCreateEntry(principal, foreignKey.PrincipalEntityType);
                    }
                    else if (foreignKey.PrincipalToDependent != null)
                    {
                        foreach (var(navigationBase, internalEntityEntry) in stateManager.GetRecordedReferrers(entry.Entity, clear: false))
                        {
                            if (navigationBase == foreignKey.PrincipalToDependent)
                            {
                                principalEntry = internalEntityEntry;
                                break;
                            }
                        }
                    }

                    if (principalEntry != null)
                    {
                        var principalProperty = foreignKey.PrincipalKey.Properties[propertyIndex];

                        if (principalProperty != property)
                        {
                            var principalValue = principalEntry[principalProperty];
                            if (generationProperty == null ||
                                !principalProperty.ClrType.IsDefaultValue(principalValue))
                            {
                                entry.PropagateValue(principalEntry, principalProperty, property);

                                return(principalEntry);
                            }
                        }
                    }

                    break;
                }
            }
        }

        return(null);
    }
示例#7
0
        public EntityEntryGraphNode(
            InternalEntityEntry entry,
            InternalEntityEntry?sourceEntry,
            INavigationBase?inboundNavigation)
        {
            Check.NotNull(entry, nameof(entry));

            _entry            = entry;
            _sourceEntry      = sourceEntry;
            InboundNavigation = inboundNavigation;
        }
示例#8
0
    /// <summary>
    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
    ///     any release. You should only use it directly in your code with extreme caution and knowing that
    ///     doing so can result in application failures when updating to a new Entity Framework Core release.
    /// </summary>
    public virtual InternalEntityEntry?Propagate(InternalEntityEntry entry)
    {
        InternalEntityEntry?chosenPrincipal = null;

        foreach (var property in entry.EntityType.GetForeignKeyProperties())
        {
            if (!entry.HasDefaultValue(property))
            {
                continue;
            }

            var principalEntry = _keyPropagator.PropagateValue(entry, property);
            chosenPrincipal ??= principalEntry;
        }

        return(chosenPrincipal);
    }
示例#9
0
            public int Compare(InternalEntityEntry?x, InternalEntityEntry?y)
            {
                if (ReferenceEquals(x, y))
                {
                    return(0);
                }

                if (x is null)
                {
                    return(-1);
                }

                if (y is null)
                {
                    return(1);
                }

                var result = StringComparer.InvariantCulture.Compare(x.EntityType.Name, y.EntityType.Name);

                if (result != 0)
                {
                    return(result);
                }

                var primaryKey = x.EntityType.FindPrimaryKey();

                if (primaryKey != null)
                {
                    var keyProperties = primaryKey.Properties;
                    foreach (var keyProperty in keyProperties)
                    {
                        var comparer = keyProperty.GetCurrentValueComparer();
                        result = comparer.Compare(x, y);
                        if (result != 0)
                        {
                            return(result);
                        }
                    }
                }

                return(0);
            }