Пример #1
0
        private void DiagnoseKeyCollision(UpdateCompiler compiler, PropagatorResult change, CompositeKey key, PropagatorResult other)
        {
            KeyManager   keyManager = compiler.m_translator.KeyManager;
            CompositeKey otherKey   = new CompositeKey(GetKeyConstants(other));

            // determine if the conflict is due to shared principal key values
            bool sharedPrincipal = true;

            for (int i = 0; sharedPrincipal && i < key.KeyComponents.Length; i++)
            {
                int identifier1 = key.KeyComponents[i].Identifier;
                int identifier2 = otherKey.KeyComponents[i].Identifier;

                if (!keyManager.GetPrincipals(identifier1).Intersect(keyManager.GetPrincipals(identifier2)).Any())
                {
                    sharedPrincipal = false;
                }
            }

            if (sharedPrincipal)
            {
                // if the duplication is due to shared principals, there is a duplicate key exception
                var stateEntries = SourceInterpreter.GetAllStateEntries(change, compiler.m_translator, m_table)
                                   .Concat(SourceInterpreter.GetAllStateEntries(other, compiler.m_translator, m_table));
                throw EntityUtil.Update(Strings.Update_DuplicateKeys, null, stateEntries);
            }
            else
            {
                // if there are no shared principals, it implies that common dependents are the problem
                HashSet <IEntityStateEntry> commonDependents = null;
                foreach (PropagatorResult keyValue in key.KeyComponents.Concat(otherKey.KeyComponents))
                {
                    var dependents = new HashSet <IEntityStateEntry>();
                    foreach (int dependentId in keyManager.GetDependents(keyValue.Identifier))
                    {
                        PropagatorResult dependentResult;
                        if (keyManager.TryGetIdentifierOwner(dependentId, out dependentResult) &&
                            null != dependentResult.StateEntry)
                        {
                            dependents.Add(dependentResult.StateEntry);
                        }
                    }
                    if (null == commonDependents)
                    {
                        commonDependents = new HashSet <IEntityStateEntry>(dependents);
                    }
                    else
                    {
                        commonDependents.IntersectWith(dependents);
                    }
                }

                // to ensure the exception shape is consistent with constraint violations discovered while processing
                // commands (a more conventional scenario in which different tables are contributing principal values)
                // wrap a DataConstraintException in an UpdateException
                throw EntityUtil.Update(Strings.Update_GeneralExecutionException,
                                        EntityUtil.Constraint(Strings.Update_ReferentialConstraintIntegrityViolation), commonDependents);
            }
        }
            internal override PropagatorResult Merge(KeyManager keyManager, PropagatorResult other)
            {
                KeyValue otherKey = other as KeyValue;

                if (null == otherKey)
                {
                    EntityUtil.InternalError(EntityUtil.InternalErrorCode.UpdatePipelineResultRequestInvalid, 0, "KeyValue.Merge");
                }

                // Determine which key (this or otherKey) is first in the chain. Principal keys take
                // precedence over dependent keys and entities take precedence over relationships.
                if (this.Identifier != otherKey.Identifier)
                {
                    // Find principal (if any)
                    if (keyManager.GetPrincipals(otherKey.Identifier).Contains(this.Identifier))
                    {
                        return(this.ReplicateResultWithNewNext(otherKey));
                    }
                    else
                    {
                        return(otherKey.ReplicateResultWithNewNext(this));
                    }
                }
                else
                {
                    // Entity takes precedence of relationship
                    if (null == m_stateEntry || m_stateEntry.IsRelationship)
                    {
                        return(otherKey.ReplicateResultWithNewNext(this));
                    }
                    else
                    {
                        return(this.ReplicateResultWithNewNext(otherKey));
                    }
                }
            }