Esempio n. 1
0
        /// <summary>
        ///     Returns the default name that would be used for this index.
        /// </summary>
        /// <param name="index"> The index. </param>
        /// <param name="storeObject"> The identifier of the store object. </param>
        /// <returns> The default name that would be used for this index. </returns>
        public static string GetDefaultDatabaseName([NotNull] this IIndex index, StoreObjectIdentifier storeObject)
        {
            var propertyNames = index.Properties.Select(p => p.GetColumnName(storeObject)).ToList();
            var rootIndex     = index;

            // Limit traversal to avoid getting stuck in a cycle (validation will throw for these later)
            // Using a hashset is detrimental to the perf when there are no cycles
            for (var i = 0; i < Metadata.Internal.RelationalEntityTypeExtensions.MaxEntityTypesSharingTable; i++)
            {
                var linkedIndex = rootIndex.DeclaringEntityType
                                  .FindRowInternalForeignKeys(storeObject)
                                  .SelectMany(fk => fk.PrincipalEntityType.GetIndexes())
                                  .FirstOrDefault(i => i.Properties.Select(p => p.GetColumnName(storeObject)).SequenceEqual(propertyNames));
                if (linkedIndex == null)
                {
                    break;
                }

                rootIndex = linkedIndex;
            }

            if (rootIndex != index)
            {
                return(rootIndex.GetDatabaseName(storeObject));
            }

            var baseName = new StringBuilder()
                           .Append("IX_")
                           .Append(storeObject.Name)
                           .Append("_")
                           .AppendJoin(propertyNames, "_")
                           .ToString();

            return(Uniquifier.Truncate(baseName, index.DeclaringEntityType.Model.GetMaxIdentifierLength()));
        }
Esempio n. 2
0
        /// <summary>
        ///     Returns the default key constraint name that would be used for this key.
        /// </summary>
        /// <param name="key"> The key. </param>
        /// <returns> The default key constraint name that would be used for this key. </returns>
        public static string GetDefaultName([NotNull] this IKey key)
        {
            var sharedTablePrincipalPrimaryKeyProperty = key.Properties[0].FindSharedRootPrimaryKeyProperty();

            if (sharedTablePrincipalPrimaryKeyProperty != null)
            {
                return(sharedTablePrincipalPrimaryKeyProperty.FindContainingPrimaryKey().GetName());
            }

            var builder   = new StringBuilder();
            var tableName = key.DeclaringEntityType.GetTableName() ?? key.DeclaringEntityType.GetViewName();

            if (key.IsPrimaryKey())
            {
                builder
                .Append("PK_")
                .Append(tableName);
            }
            else
            {
                builder
                .Append("AK_")
                .Append(tableName)
                .Append("_")
                .AppendJoin(key.Properties.Select(p => p.GetColumnName()), "_");
            }

            return(Uniquifier.Truncate(builder.ToString(), key.DeclaringEntityType.Model.GetMaxIdentifierLength()));
        }
    /// <summary>
    ///     Returns the default table name that would be used for this entity type.
    /// </summary>
    /// <param name="entityType">The entity type to get the table name for.</param>
    /// <param name="truncate">A value indicating whether the name should be truncated to the max identifier length.</param>
    /// <returns>The default name of the table to which the entity type would be mapped.</returns>
    public static string?GetDefaultTableName(this IReadOnlyEntityType entityType, bool truncate = true)
    {
        var ownership = entityType.FindOwnership();

        if (ownership != null &&
            ownership.IsUnique)
        {
            return(ownership.PrincipalEntityType.GetTableName());
        }

        var name = entityType.ShortName();

        if (entityType.HasSharedClrType &&
            ownership != null
#pragma warning disable EF1001 // Internal EF Core API usage.
            && entityType.Name == ownership.PrincipalEntityType.GetOwnedName(name, ownership.PrincipalToDependent !.Name))
#pragma warning restore EF1001 // Internal EF Core API usage.
        {
            var ownerTypeTable = ownership.PrincipalEntityType.GetTableName();
            name = ownerTypeTable != null
                ? $"{ownerTypeTable}_{ownership.PrincipalToDependent.Name}"
                : $"{ownership.PrincipalToDependent.Name}_{name}";
        }

        return(truncate
            ? Uniquifier.Truncate(name, entityType.Model.GetMaxIdentifierLength())
            : name);
    }
Esempio n. 4
0
        /// <summary>
        ///     Generates a unique name for the new joint entity type.
        /// </summary>
        /// <param name="skipNavigation">The target skip navigation.</param>
        /// <returns>A unique entity type name.</returns>
        protected virtual string GenerateJoinTypeName(IConventionSkipNavigation skipNavigation)
        {
            var inverseSkipNavigation = skipNavigation.Inverse;

            Check.DebugAssert(
                inverseSkipNavigation?.Inverse == skipNavigation,
                "Inverse's inverse should be the original skip navigation");

            var declaringEntityType = skipNavigation.DeclaringEntityType;
            var inverseEntityType   = inverseSkipNavigation.DeclaringEntityType;
            var model = declaringEntityType.Model;
            var joinEntityTypeName = declaringEntityType.ShortName();
            var inverseName        = inverseEntityType.ShortName();

            joinEntityTypeName = StringComparer.Ordinal.Compare(joinEntityTypeName, inverseName) < 0
                ? joinEntityTypeName + inverseName
                : inverseName + joinEntityTypeName;

            if (model.FindEntityType(joinEntityTypeName) != null)
            {
                var otherIdentifiers = model.GetEntityTypes().ToDictionary(et => et.Name, _ => 0);
                joinEntityTypeName = Uniquifier.Uniquify(
                    joinEntityTypeName,
                    otherIdentifiers,
                    int.MaxValue);
            }

            return(joinEntityTypeName);
        }
Esempio n. 5
0
        private void CreateJoinEntityType(IConventionSkipNavigationBuilder skipNavigationBuilder)
        {
            var skipNavigation = (SkipNavigation)skipNavigationBuilder.Metadata;

            if (skipNavigation.ForeignKey != null ||
                !skipNavigation.IsCollection)
            {
                return;
            }

            var inverseSkipNavigation = skipNavigation.Inverse;

            if (inverseSkipNavigation == null ||
                inverseSkipNavigation.ForeignKey != null ||
                !inverseSkipNavigation.IsCollection)
            {
                return;
            }

            Check.DebugAssert(inverseSkipNavigation.Inverse == skipNavigation,
                              "Inverse's inverse should be the original skip navigation");

            var declaringEntityType = skipNavigation.DeclaringEntityType;
            var inverseEntityType   = inverseSkipNavigation.DeclaringEntityType;
            var model = declaringEntityType.Model;

            var joinEntityTypeName = declaringEntityType.ShortName() + inverseEntityType.ShortName();

            if (model.FindEntityType(joinEntityTypeName) != null)
            {
                var otherIdentifiers = model.GetEntityTypes().ToDictionary(et => et.Name, et => 0);
                joinEntityTypeName = Uniquifier.Uniquify(
                    joinEntityTypeName,
                    otherIdentifiers,
                    int.MaxValue);
            }

            var joinEntityTypeBuilder = model.Builder.SharedTypeEntity(
                joinEntityTypeName, Model.DefaultPropertyBagType, ConfigurationSource.Convention);

            var leftForeignKey = CreateSkipNavigationForeignKey(skipNavigation, joinEntityTypeBuilder);

            if (leftForeignKey == null)
            {
                model.Builder.HasNoEntityType(joinEntityTypeBuilder.Metadata, ConfigurationSource.Convention);
                return;
            }

            var rightForeignKey = CreateSkipNavigationForeignKey(inverseSkipNavigation, joinEntityTypeBuilder);

            if (rightForeignKey == null)
            {
                model.Builder.HasNoEntityType(joinEntityTypeBuilder.Metadata, ConfigurationSource.Convention);
                return;
            }

            skipNavigation.Builder.HasForeignKey(leftForeignKey, ConfigurationSource.Convention);
            inverseSkipNavigation.Builder.HasForeignKey(rightForeignKey, ConfigurationSource.Convention);
        }
        private static string GetDefaultName(IIndex index)
        {
            var baseName = new StringBuilder()
                           .Append(index.DeclaringEntityType.GetTableName())
                           .Append("_ix_")
                           .AppendJoin("_", index.Properties.Select(p => p.GetColumnName()))
                           .ToString();

            return(Uniquifier.Truncate(baseName, index.DeclaringEntityType.Model.GetMaxIdentifierLength()));
        }
        private static string?FindArglistParameterName(IMethodSymbol symbol)
        {
            if (symbol.IsVararg)
            {
                var uniquifier = new Uniquifier(symbol.Parameters.Select(a => a.Name));
                return(uniquifier.GetUniqueName("arglist"));
            }

            return(null);
        }
        public SingleTypeOrValueTuple Build(string?mockMemberName = null)
        {
            mockMemberName ??= string.Empty;

            int count = Items.Count;

            SingleTypeOrValueTuple.Entry[] entries = new SingleTypeOrValueTuple.Entry[Items.Count];

            if (count > 0)
            {
                if (count > 1)
                {
                    var uniquifier = new Uniquifier(new[] { mockMemberName });

                    for (int i = 0; i < count; i++)
                    {
                        var    item = Items[i];
                        string name = item.OriginalName;
                        name = name == mockMemberName ? name + "_" : name;
                        if (IsNameValidForPosition(name, i))
                        {
                            entries[i] = new SingleTypeOrValueTuple.Entry(
                                item.OriginalName,
                                item.Type,
                                item.IsReturnValue,
                                uniquifier.GetUniqueName(name));
                        }
                    }

                    for (int i = 0; i < count; i++)
                    {
                        var    item = Items[i];
                        string name = item.OriginalName;
                        name = name == mockMemberName ? name + "_" : name;
                        if (!IsNameValidForPosition(name, i))
                        {
                            entries[i] = new SingleTypeOrValueTuple.Entry(
                                item.OriginalName,
                                item.Type,
                                item.IsReturnValue,
                                uniquifier.GetUniqueName(name + "_"));
                        }
                    }
                }
                else
                {
                    var    item = Items[0];
                    string name = item.OriginalName;
                    name       = name == mockMemberName ? name + "_" : name;
                    entries[0] = new SingleTypeOrValueTuple.Entry(item.OriginalName, item.Type, item.IsReturnValue, name);
                }
            }

            return(new SingleTypeOrValueTuple(entries));
        }
        /// <summary>
        ///     Returns the default column name to which the property would be mapped.
        /// </summary>
        /// <param name="property"> The property. </param>
        /// <returns> The default column name to which the property would be mapped. </returns>
        public static string GetDefaultColumnName([NotNull] this IProperty property)
        {
            var sharedTablePrincipalPrimaryKeyProperty = property.FindSharedTableRootPrimaryKeyProperty();

            if (sharedTablePrincipalPrimaryKeyProperty != null)
            {
                return(sharedTablePrincipalPrimaryKeyProperty.GetColumnName());
            }

            var           entityType = property.DeclaringEntityType;
            StringBuilder builder    = null;

            do
            {
                var ownership = entityType.GetForeignKeys().SingleOrDefault(fk => fk.IsOwnership);
                if (ownership == null)
                {
                    entityType = null;
                }
                else
                {
                    var ownerType = ownership.PrincipalEntityType;
                    var table     = entityType.GetTableName();
                    if (table != null &&
                        table == ownerType.GetTableName() &&
                        entityType.GetSchema() == ownerType.GetSchema())
                    {
                        if (builder == null)
                        {
                            builder = new StringBuilder();
                        }

                        builder.Insert(0, "_");
                        builder.Insert(0, ownership.PrincipalToDependent.Name);
                        entityType = ownerType;
                    }
                    else
                    {
                        entityType = null;
                    }
                }
            }while (entityType != null);

            var baseName = property.Name;

            if (builder != null)
            {
                builder.Append(baseName);
                baseName = builder.ToString();
            }

            return(Uniquifier.Truncate(baseName, property.DeclaringEntityType.Model.GetMaxIdentifierLength()));
        }
    /// <summary>
    ///     Returns the default name that would be used for this index.
    /// </summary>
    /// <param name="index">The index.</param>
    /// <returns>The default name that would be used for this index.</returns>
    public static string GetDefaultDatabaseName(this IReadOnlyIndex index)
    {
        var tableName = index.DeclaringEntityType.GetTableName();
        var baseName  = new StringBuilder()
                        .Append("IX_")
                        .Append(tableName)
                        .Append('_')
                        .AppendJoin(index.Properties.Select(p => p.GetColumnBaseName()), "_")
                        .ToString();

        return(Uniquifier.Truncate(baseName, index.DeclaringEntityType.Model.GetMaxIdentifierLength()));
    }
        private static string GetDefaultName(IMutableForeignKey key)
        {
            var baseName = new StringBuilder()
                           .Append(key.DeclaringEntityType.GetTableName())
                           .Append("_")
                           .Append(key.PrincipalEntityType.GetTableName())
                           .Append("_")
                           .AppendJoin("_", key.PrincipalKey.Properties.Select(p => p.GetColumnName()))
                           .Append("_fkey")
                           .ToString();

            return(Uniquifier.Truncate(baseName, key.DeclaringEntityType.Model.GetMaxIdentifierLength()));
        }
Esempio n. 12
0
        /// <summary>
        ///     Returns the default constraint name that would be used for this foreign key.
        /// </summary>
        /// <param name="foreignKey"> The foreign key. </param>
        /// <returns> The default constraint name that would be used for this foreign key. </returns>
        public static string GetDefaultName([NotNull] this IForeignKey foreignKey)
        {
            var baseName = new StringBuilder()
                           .Append("FK_")
                           .Append(foreignKey.DeclaringEntityType.GetTableName())
                           .Append("_")
                           .Append(foreignKey.PrincipalEntityType.GetTableName())
                           .Append("_")
                           .AppendJoin(foreignKey.Properties.Select(p => p.GetColumnName()), "_")
                           .ToString();

            return(Uniquifier.Truncate(baseName, foreignKey.DeclaringEntityType.Model.GetMaxIdentifierLength()));
        }
Esempio n. 13
0
        /// <summary>
        ///     Returns the default name that would be used for this index.
        /// </summary>
        /// <param name="index"> The index. </param>
        /// <returns> The default name that would be used for this index. </returns>
        public static string GetDefaultName([NotNull] this IIndex index)
        {
            var tableName = index.DeclaringEntityType.GetTableName();
            var schema    = index.DeclaringEntityType.GetSchema();
            var baseName  = new StringBuilder()
                            .Append("IX_")
                            .Append(tableName)
                            .Append("_")
                            .AppendJoin(index.Properties.Select(p => p.GetColumnName(tableName, schema)), "_")
                            .ToString();

            return(Uniquifier.Truncate(baseName, index.DeclaringEntityType.Model.GetMaxIdentifierLength()));
        }
        private MemberDeclarationSyntax MockSetVirtualMethod()
        {
            var uniquifier = new Uniquifier(Symbol.Parameters.Select(p => p.Name));

            var parameterList = F.SeparatedList(Symbol.Parameters.Select(a =>
                                                                         F.Parameter(F.Identifier(a.Name)).WithType(TypesForSymbols.ParseTypeName(a.Type, a.NullableOrOblivious()))))
                                .Add(F.Parameter(F.Identifier(uniquifier.GetUniqueName("value"))).WithType(ValueTypeSyntax));

            return(F.MethodDeclaration(F.PredefinedType(F.Token(SyntaxKind.VoidKeyword)), F.Identifier(MemberMockName))
                   .WithModifiers(F.TokenList(F.Token(SyntaxKind.ProtectedKeyword), F.Token(SyntaxKind.VirtualKeyword)))
                   .WithParameterList(F.ParameterList(parameterList))
                   .WithBody(F.Block(ThrowMockMissingStatement("VirtualIndexerSet"))));
        }
Esempio n. 15
0
        /// <summary>
        ///     Returns the default table name that would be used for this entity type.
        /// </summary>
        /// <param name="entityType"> The entity type to get the table name for. </param>
        /// <returns> The default name of the table to which the entity type would be mapped. </returns>
        public static string GetDefaultTableName([NotNull] this IEntityType entityType)
        {
            var ownership = entityType.FindOwnership();

            if (ownership != null &&
                ownership.IsUnique)
            {
                return(ownership.PrincipalEntityType.GetTableName());
            }

            return(Uniquifier.Truncate(
                       entityType.HasDefiningNavigation()
                    ? $"{entityType.DefiningEntityType.GetTableName()}_{entityType.DefiningNavigationName}"
                    : entityType.ShortName(),
                       entityType.Model.GetMaxIdentifierLength()));
        }
Esempio n. 16
0
        private MocklisTypesForSymbols(SemanticModel semanticModel, ClassDeclarationSyntax classDeclaration, MocklisSymbols mocklisSymbols,
                                       INamedTypeSymbol classSymbol, IMethodSymbol methodSymbol, bool nullableContextEnabled)
        {
            _semanticModel    = semanticModel;
            _classDeclaration = classDeclaration;
            _mocklisSymbols   = mocklisSymbols;
            _typeParameterNameSubstitutions = new Dictionary <string, string>();
            _nullableContextEnabled         = nullableContextEnabled;
            Uniquifier t = new Uniquifier(classSymbol.TypeParameters.Select(tp => tp.Name));

            foreach (var methodTypeParameter in methodSymbol.TypeParameters)
            {
                string uniqueName = t.GetUniqueName(methodTypeParameter.Name);
                _typeParameterNameSubstitutions[methodTypeParameter.Name] = uniqueName;
            }
        }
        /// <summary>
        ///     Returns the default constraint name that would be used for this foreign key.
        /// </summary>
        /// <param name="foreignKey"> The foreign key. </param>
        /// <param name="tableName"> The table name. </param>
        /// <param name="schema"> The schema. </param>
        /// <param name="principalTableName"> The principal table name. </param>
        /// <param name="principalSchema"> The principal schema. </param>
        /// <returns> The default constraint name that would be used for this foreign key. </returns>
        public static string GetDefaultName(
            [NotNull] this IForeignKey foreignKey,
            [NotNull] string tableName,
            [CanBeNull] string schema,
            [NotNull] string principalTableName,
            [CanBeNull] string principalSchema)
        {
            var storeObject            = StoreObjectIdentifier.Table(tableName, schema);
            var propertyNames          = foreignKey.Properties.Select(p => p.GetColumnName(storeObject)).ToList();
            var principalPropertyNames = foreignKey.PrincipalKey.Properties.Select(p => p.GetColumnName(storeObject)).ToList();
            var rootForeignKey         = foreignKey;

            // Limit traversal to avoid getting stuck in a cycle (validation will throw for these later)
            // Using a hashset is detrimental to the perf when there are no cycles
            for (var i = 0; i < Metadata.Internal.RelationalEntityTypeExtensions.MaxEntityTypesSharingTable; i++)
            {
                var linkedForeignKey = rootForeignKey.DeclaringEntityType
                                       .FindRowInternalForeignKeys(storeObject)
                                       .SelectMany(fk => fk.PrincipalEntityType.GetForeignKeys())
                                       .FirstOrDefault(k => principalTableName == k.PrincipalEntityType.GetTableName() &&
                                                       principalSchema == k.PrincipalEntityType.GetSchema() &&
                                                       propertyNames.SequenceEqual(k.Properties.Select(p => p.GetColumnName(storeObject))) &&
                                                       principalPropertyNames.SequenceEqual(k.PrincipalKey.Properties.Select(p => p.GetColumnName(storeObject))));
                if (linkedForeignKey == null)
                {
                    break;
                }

                rootForeignKey = linkedForeignKey;
            }

            if (rootForeignKey != foreignKey)
            {
                return(rootForeignKey.GetConstraintName(tableName, schema, principalTableName, principalSchema));
            }

            var baseName = new StringBuilder()
                           .Append("FK_")
                           .Append(tableName)
                           .Append("_")
                           .Append(principalTableName)
                           .Append("_")
                           .AppendJoin(foreignKey.Properties.Select(p => p.GetColumnName(storeObject)), "_")
                           .ToString();

            return(Uniquifier.Truncate(baseName, foreignKey.DeclaringEntityType.Model.GetMaxIdentifierLength()));
        }
Esempio n. 18
0
        static CloudBlockBlob GetUniqueBlobName(string uploadedFileName, FileInfo fileInfo, CloudBlobContainer container)
        {
            var length      = fileInfo.Length;
            var packageBlob = Uniquifier.UniquifyUntil(
                uploadedFileName,
                container.GetBlockBlobReference,
                blob =>
            {
                if (blob.Exists() && blob.Properties.Length != length)
                {
                    Log.Verbose("A blob named " + blob.Name + " already exists but has a different length.");
                    return(true);
                }

                return(false);
            });

            return(packageBlob);
        }
Esempio n. 19
0
        /// <summary>
        ///     Returns the default key constraint name that would be used for this key.
        /// </summary>
        /// <param name="key"> The key. </param>
        /// <returns> The default key constraint name that would be used for this key. </returns>
        public static string GetDefaultName([NotNull] this IKey key)
        {
            string name      = null;
            var    tableName = key.DeclaringEntityType.GetTableName();

            if (key.IsPrimaryKey())
            {
                name = "PK_" + tableName;
            }
            else
            {
                name = new StringBuilder()
                       .Append("AK_")
                       .Append(tableName)
                       .Append("_")
                       .AppendJoin(key.Properties.Select(p => p.GetColumnName()), "_")
                       .ToString();
            }

            return(Uniquifier.Truncate(name, key.DeclaringEntityType.Model.GetMaxIdentifierLength()));
        }
        /// <inheritdoc />
        public virtual void ProcessModelFinalizing(IConventionModelBuilder modelBuilder, IConventionContext <IConventionModelBuilder> context)
        {
            var model          = modelBuilder.Metadata;
            var modelSequences =
                (SortedDictionary <(string Name, string Schema), Sequence>)model[RelationalAnnotationNames.Sequences];

            if (modelSequences != null)
            {
                var maxLength = model.GetMaxIdentifierLength();
                var toReplace = modelSequences
                                .Where(s => s.Key.Name.Length > maxLength).ToList();

                foreach (var sequence in toReplace)
                {
                    var schemaName      = sequence.Key.Schema;
                    var newSequenceName = Uniquifier.Uniquify(
                        sequence.Key.Name, modelSequences,
                        sequenceName => (sequenceName, schemaName), maxLength);
                    Sequence.SetName((IMutableModel)model, sequence.Value, newSequenceName);
                }
            }
        }
Esempio n. 21
0
        private static ForeignKey CreateSkipNavigationForeignKey(
            SkipNavigation skipNavigation,
            InternalEntityTypeBuilder associationEntityTypeBuilder)
        {
            var principalEntityType = skipNavigation.DeclaringEntityType;
            var principalKey        = principalEntityType.FindPrimaryKey();

            if (principalKey == null)
            {
                return(null);
            }

            var dependentEndForeignKeyPropertyNames = new List <string>();
            var otherIdentifiers = associationEntityTypeBuilder.Metadata
                                   .GetDeclaredProperties().ToDictionary(p => p.Name, p => 0);

            foreach (var property in principalKey.Properties)
            {
                var propertyName = Uniquifier.Uniquify(
                    string.Format(
                        AssociationPropertyNameTemplate,
                        principalEntityType.ShortName(),
                        property.Name),
                    otherIdentifiers,
                    int.MaxValue);
                dependentEndForeignKeyPropertyNames.Add(propertyName);
                otherIdentifiers.Add(propertyName, 0);
            }

            return(associationEntityTypeBuilder
                   .HasRelationship(
                       principalEntityType.Name,
                       dependentEndForeignKeyPropertyNames,
                       principalKey,
                       ConfigurationSource.Convention)
                   .IsUnique(false, ConfigurationSource.Convention)
                   .Metadata);
        }
        /// <summary>
        ///     Returns the default table name that would be used for this entity type.
        /// </summary>
        /// <param name="entityType"> The entity type to get the table name for. </param>
        /// <param name="truncate"> A value indicating whether the name should be truncated to the max identifier length. </param>
        /// <returns> The default name of the table to which the entity type would be mapped. </returns>
        public static string GetDefaultTableName([NotNull] this IEntityType entityType, bool truncate = true)
        {
            var ownership = entityType.FindOwnership();

            if (ownership != null &&
                ownership.IsUnique)
            {
                return(ownership.PrincipalEntityType.GetTableName());
            }

            var name = entityType.ShortName();

            if (entityType.HasDefiningNavigation())
            {
                var definingTypeName = entityType.DefiningEntityType.GetTableName();
                name = definingTypeName != null
                    ? $"{definingTypeName}_{entityType.DefiningNavigationName}"
                    : $"{entityType.DefiningNavigationName}_{name}";
            }

            return(truncate
                ? Uniquifier.Truncate(name, entityType.Model.GetMaxIdentifierLength())
                : name);
        }
Esempio n. 23
0
        private void CreateAssociationEntityType(
            IConventionSkipNavigationBuilder skipNavigationBuilder)
        {
            var skipNavigation = (SkipNavigation)skipNavigationBuilder.Metadata;

            if (skipNavigation.AssociationEntityType != null)
            {
                return;
            }

            if (skipNavigation.ForeignKey != null ||
                skipNavigation.TargetEntityType == skipNavigation.DeclaringEntityType ||
                !skipNavigation.IsCollection)
            {
                // do not create the association entity type for a self-referencing
                // skip navigation, or for one that is already "in use"
                // (i.e. has its Foreign Key assigned).
                return;
            }

            var inverseSkipNavigation = skipNavigation.Inverse;

            if (inverseSkipNavigation == null ||
                inverseSkipNavigation.ForeignKey != null ||
                !inverseSkipNavigation.IsCollection)
            {
                // do not create the association entity type if
                // the inverse skip navigation is already "in use"
                // (i.e. has its Foreign Key assigned).
                return;
            }

            Check.DebugAssert(inverseSkipNavigation.Inverse == skipNavigation,
                              "Inverse's inverse should be the original skip navigation");

            var declaringEntityType = skipNavigation.DeclaringEntityType;
            var inverseEntityType   = inverseSkipNavigation.DeclaringEntityType;
            var model = declaringEntityType.Model;

            // create the association entity type
            var associationEntityTypeName = string.Format(
                AssociationEntityTypeNameTemplate,
                declaringEntityType.ShortName(),
                inverseEntityType.ShortName());

            if (model.FindEntityType(associationEntityTypeName) != null)
            {
                var otherIdentifiers = model.GetEntityTypes().ToDictionary(et => et.Name, et => 0);
                associationEntityTypeName = Uniquifier.Uniquify(
                    associationEntityTypeName,
                    otherIdentifiers,
                    int.MaxValue);
            }

            var associationEntityTypeBuilder = model.Builder.SharedEntity(
                associationEntityTypeName, Model.DefaultPropertyBagType, ConfigurationSource.Convention);

            // Create left and right foreign keys from the outer entity types to
            // the association entity type and configure the skip navigations.
            // Roll back if any of this fails.
            var leftForeignKey =
                CreateSkipNavigationForeignKey(skipNavigation, associationEntityTypeBuilder);

            if (leftForeignKey == null)
            {
                model.Builder.HasNoEntityType(
                    associationEntityTypeBuilder.Metadata, ConfigurationSource.Convention);
                return;
            }

            var rightForeignKey =
                CreateSkipNavigationForeignKey(inverseSkipNavigation, associationEntityTypeBuilder);

            if (rightForeignKey == null)
            {
                // Removing the association entity type will also remove
                // the leftForeignKey created above.
                model.Builder.HasNoEntityType(
                    associationEntityTypeBuilder.Metadata, ConfigurationSource.Convention);
                return;
            }

            skipNavigation.Builder.HasForeignKey(leftForeignKey, ConfigurationSource.Convention);
            inverseSkipNavigation.Builder.HasForeignKey(rightForeignKey, ConfigurationSource.Convention);

            // Creating the primary key below also negates the need for an index on
            // the properties of leftForeignKey - that index is automatically removed.
            associationEntityTypeBuilder.PrimaryKey(
                leftForeignKey.Properties.Concat(rightForeignKey.Properties).ToList(),
                ConfigurationSource.Convention);
        }
Esempio n. 24
0
        /// <summary>
        ///     Returns the default key constraint name that would be used for this key for a particular table.
        /// </summary>
        /// <param name="key"> The key. </param>
        /// <param name="storeObject"> The identifier of the containing store object. </param>
        /// <returns> The default key constraint name that would be used for this key. </returns>
        public static string GetDefaultName([NotNull] this IKey key, StoreObjectIdentifier storeObject)
        {
            string name = null;

            if (key.IsPrimaryKey())
            {
                var rootKey = key;
                // Limit traversal to avoid getting stuck in a cycle (validation will throw for these later)
                // Using a hashset is detrimental to the perf when there are no cycles
                for (var i = 0; i < Metadata.Internal.RelationalEntityTypeExtensions.MaxEntityTypesSharingTable; i++)
                {
                    var linkingFk = rootKey.DeclaringEntityType.FindRowInternalForeignKeys(storeObject)
                                    .FirstOrDefault();
                    if (linkingFk == null)
                    {
                        break;
                    }

                    rootKey = linkingFk.PrincipalEntityType.FindPrimaryKey();
                }

                if (rootKey != null &&
                    rootKey != key)
                {
                    return(rootKey.GetName(storeObject));
                }

                name = "PK_" + storeObject.Name;
            }
            else
            {
                var propertyNames = key.Properties.Select(p => p.GetColumnName(storeObject)).ToList();
                var rootKey       = key;

                // Limit traversal to avoid getting stuck in a cycle (validation will throw for these later)
                // Using a hashset is detrimental to the perf when there are no cycles
                for (var i = 0; i < Metadata.Internal.RelationalEntityTypeExtensions.MaxEntityTypesSharingTable; i++)
                {
                    var linkedKey = rootKey.DeclaringEntityType
                                    .FindRowInternalForeignKeys(storeObject)
                                    .SelectMany(fk => fk.PrincipalEntityType.GetKeys())
                                    .FirstOrDefault(k => k.Properties.Select(p => p.GetColumnName(storeObject)).SequenceEqual(propertyNames));
                    if (linkedKey == null)
                    {
                        break;
                    }

                    rootKey = linkedKey;
                }

                if (rootKey != key)
                {
                    return(rootKey.GetName(storeObject));
                }

                name = new StringBuilder()
                       .Append("AK_")
                       .Append(storeObject.Name)
                       .Append("_")
                       .AppendJoin(key.Properties.Select(p => p.GetColumnName(storeObject)), "_")
                       .ToString();
            }

            return(Uniquifier.Truncate(name, key.DeclaringEntityType.Model.GetMaxIdentifierLength()));
        }
Esempio n. 25
0
        protected MemberDeclarationSyntax ExplicitInterfaceMember()
        {
            var baseReturnType = Symbol.ReturnsVoid
                ? F.PredefinedType(F.Token(SyntaxKind.VoidKeyword))
                : TypesForSymbols.ParseTypeName(Symbol.ReturnType, Symbol.ReturnTypeIsNullableOrOblivious());
            var returnType = baseReturnType;

            if (Symbol.ReturnsByRef)
            {
                returnType = F.RefType(returnType);
            }
            else if (Symbol.ReturnsByRefReadonly)
            {
                returnType = F.RefType(returnType).WithReadOnlyKeyword(F.Token(SyntaxKind.ReadOnlyKeyword));
            }

            var mockedMethod = ExplicitInterfaceMemberMethodDeclaration(returnType);

            var memberMockInstance = ExplicitInterfaceMemberMemberMockInstance();

            ExpressionSyntax invocation = F.InvocationExpression(
                F.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                         memberMockInstance, F.IdentifierName("Call")))
                                          .WithExpressionsAsArgumentList(ParametersType.BuildArgumentListWithOriginalNames());

            // look at the return parameters. If we don't have any we can just make the call.
            // if we only have one and that's the return value, we can just return it.
            if (ReturnValuesType.Count == 0 ||
                ReturnValuesType.Count == 1 && ReturnValuesType[0].IsReturnValue)
            {
                if (Symbol.ReturnsByRef || Symbol.ReturnsByRefReadonly)
                {
                    invocation = TypesForSymbols.WrapByRef(invocation, baseReturnType);
                }

                mockedMethod = mockedMethod.WithExpressionBody(F.ArrowExpressionClause(invocation))
                               .WithSemicolonToken(F.Token(SyntaxKind.SemicolonToken));
            }
            // if we only have one and that's not a return value, we can just assign it to the out or ref parameter it corresponds to.
            else if (ReturnValuesType.Count == 1)
            {
                mockedMethod = mockedMethod.WithBody(F.Block(F.ExpressionStatement(F.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
                                                                                                          F.IdentifierName(ReturnValuesType[0].OriginalName), invocation))));
            }
            else
            {
                // if we have more than one, put it in a temporary variable. (consider name clashes with method parameter names)
                var    x   = new Uniquifier(Symbol.Parameters.Select(m => m.Name));
                string tmp = x.GetUniqueName("tmp");

                var statements = new List <StatementSyntax>
                {
                    F.LocalDeclarationStatement(F.VariableDeclaration(F.IdentifierName("var")).WithVariables(
                                                    F.SingletonSeparatedList(F.VariableDeclarator(F.Identifier(tmp)).WithInitializer(F.EqualsValueClause(invocation)))))
                };

                // then for any out or ref parameters, set their values from the temporary variable.
                foreach (var rv in ReturnValuesType.Where(a => !a.IsReturnValue))
                {
                    statements.Add(F.ExpressionStatement(F.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
                                                                                F.IdentifierName(rv.OriginalName),
                                                                                F.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, F.IdentifierName(tmp),
                                                                                                         F.IdentifierName(rv.TupleSafeName)))));
                }

                // finally, if there is a 'proper' return type, return the corresponding value from the temporary variable.
                foreach (var rv in ReturnValuesType.Where(a => a.IsReturnValue))
                {
                    ExpressionSyntax memberAccess = F.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, F.IdentifierName(tmp),
                                                                             F.IdentifierName(rv.TupleSafeName));

                    if (Symbol.ReturnsByRef || Symbol.ReturnsByRefReadonly)
                    {
                        memberAccess = TypesForSymbols.WrapByRef(memberAccess, baseReturnType);
                    }

                    statements.Add(F.ReturnStatement(memberAccess));
                }

                mockedMethod = mockedMethod.WithBody(F.Block(statements));
            }

            return(mockedMethod);
        }