Example #1
0
        protected virtual bool SetDefaultValue(object value)
        {
            if (value != null)
            {
                var valueType = value.GetType();
                if (Property.ClrType.UnwrapNullableType() != valueType)
                {
                    try
                    {
                        value = Convert.ChangeType(value, Property.ClrType, CultureInfo.InvariantCulture);
                    }
                    catch (Exception)
                    {
                        throw new InvalidOperationException(ResX.IncorrectDefaultValueType(value, valueType, Property.Name, Property.ClrType, Property.DeclaringEntity.Name));
                    }
                }

                if (valueType.GetTypeInfo().IsEnum)
                {
                    value = Convert.ChangeType(value, valueType.UnwrapEnumType(), CultureInfo.InvariantCulture);
                }
            }

            if (!ShouldThrowOnConflict && DefaultValue != value && value != null)
            {
                ClearAllServerGeneratedValues();
            }

            Metadata[RelationalAnnotationNames.DefaultValue] = value;

            return(true);
        }
Example #2
0
        public static bool AreCompatible(IReadOnlyList <Property> principalProperties, IReadOnlyList <Property> dependentProperties, Entity principalEntity, Entity dependentEntity, bool shouldThrow)
        {
            Check.NotNull(principalProperties, nameof(principalProperties));
            Check.NotNull(dependentProperties, nameof(dependentProperties));
            Check.NotNull(principalEntity, nameof(principalEntity));
            Check.NotNull(dependentEntity, nameof(dependentEntity));

            if (!ArePropertyCountsEqual(principalProperties, dependentProperties))
            {
                if (shouldThrow)
                {
                    throw new InvalidOperationException(ResX.ForeignKeyCountMismatch(Property.Format(dependentProperties), dependentEntity.Name, Property.Format(principalProperties), principalEntity.Name));
                }
                return(false);
            }

            if (!ArePropertyTypesCompatible(principalProperties, dependentProperties))
            {
                if (shouldThrow)
                {
                    throw new InvalidOperationException(ResX.ForeignKeyTypeMismatch(Property.Format(dependentProperties), dependentEntity.Name, Property.Format(principalProperties), principalEntity.Name));
                }
                return(false);
            }

            return(true);
        }
Example #3
0
        protected virtual bool CanSetDefaultValueSql(string value)
        {
            if (DefaultValueSql == value)
            {
                return(true);
            }

            if (ShouldThrowOnConflict)
            {
                if (DefaultValue != null)
                {
                    throw new InvalidOperationException(ResX.ConflictingColumnServerGeneration(nameof(DefaultValueSql), Property.Name, nameof(DefaultValue)));
                }

                if (ComputedColumnSql != null)
                {
                    throw new InvalidOperationException(ResX.ConflictingColumnServerGeneration(nameof(DefaultValueSql), Property.Name, nameof(ComputedColumnSql)));
                }
            }
            else if (value != null && (!CanSetDefaultValue(null) || !CanSetComputedColumnSql(null)))
            {
                return(false);
            }

            return(true);
        }
Example #4
0
        /// <summary>
        ///     Sets the primary key for this entity.
        /// </summary>
        /// <param name="properties"> The properties that make up the primary key. </param>
        /// <returns> The newly created key. </returns>
        internal Key SetPrimaryKey(IReadOnlyList <Property> properties)
        {
            Check.NotEmpty(properties, nameof(properties));
            Check.HasNoNulls(properties, nameof(properties));

            if (_baseType != null)
            {
                throw new InvalidOperationException(ResX.DerivedEntityKey(Name, _baseType.Name));
            }

            if (_primaryKey != null)
            {
                throw new InvalidOperationException(ResX.PrimaryKeyAlreadyExists);
            }

            Key key = GetOrAddKey(properties);

            foreach (var property in key.Properties)
            {
                _properties.Remove(property.Name);
                property.PrimaryKey = key;
            }

            _primaryKey = key;

            foreach (var property in key.Properties)
            {
                _properties.Add(property.Name, property);
            }

            return(_primaryKey);
        }
Example #5
0
        internal Navigation AddNavigation(PropertyInfo navigationProperty, ForeignKey fkToLinkedEntity, ForeignKey fkToTargetedEntity)
        {
            Check.NotNull(navigationProperty, nameof(navigationProperty));
            Check.NotNull(fkToLinkedEntity, nameof(fkToLinkedEntity));
            Check.NotNull(fkToTargetedEntity, nameof(fkToTargetedEntity));

            var name = navigationProperty.Name;
            var duplicateNavigation = FindNavigationsInHierarchy(name).FirstOrDefault();

            if (duplicateNavigation != null)
            {
                throw new InvalidOperationException(ResX.DuplicateNavigation(name, Name, duplicateNavigation.DeclaringEntity.Name));
            }

            var duplicateProperty = FindPropertiesInHierarchy(name).FirstOrDefault();

            if (duplicateProperty != null)
            {
                throw new InvalidOperationException(ResX.ConflictingProperty(name, Name, duplicateProperty.DeclaringEntity.Name));
            }

            var navigation = new Navigation(navigationProperty, fkToLinkedEntity, fkToTargetedEntity);

            _navigations.Add(name, navigation);

            return(navigation);
        }
Example #6
0
        /// <summary>
        ///     <para>
        ///         Add a shadow entity to this model used to represent a many to many association between two entities.
        ///     </para>
        ///     <para>
        ///         Add PK
        ///         Add FK targeting <paramref name="entity1"/>
        ///         Add FK targeting <paramref name="entity2"/> .
        ///     </para>
        /// </summary>
        /// <param name="name"> The name of the entity to be added. </param>
        /// <param name="entity1"> Declaring entity </param>
        /// <param name="entity2"> Targeting entity </param>
        /// <returns> The new entity. </returns>
        internal Entity AddLinkedEntity(string name, Entity entity1, Entity entity2)
        {
            Check.NotEmpty(name, nameof(name));
            Check.NotNull(entity1, nameof(entity1));
            Check.NotNull(entity2, nameof(entity2));

            if (FindEntity(name) != null)
            {
                throw new InvalidOperationException(ResX.DuplicateEntity(name));
            }

            var linkedEntity = AddEntity(name, runConventions: false);

            Func <Entity, List <Property> > addPropertiesToLinkedEntity = (entity) =>
            {
                var properties = new List <Property>();
                entity.FindPrimaryKey().Properties.ToList().ForEach(x =>
                {
                    string propertyName = x.Name.Equals("Id", StringComparison.OrdinalIgnoreCase) ? "Id" + x.DeclaringEntity.Name : x.Name;
                    properties.Add(linkedEntity.AddProperty(x.Clone(linkedEntity, propertyName)));
                });
                return(properties);
            };

            var propertiesFromEntity1  = addPropertiesToLinkedEntity(entity1);
            var propertiesFromEntity2  = addPropertiesToLinkedEntity(entity2);
            var linkedEntityProperties = propertiesFromEntity1.Concat(propertiesFromEntity2).ToList();

            linkedEntity.SetPrimaryKey(linkedEntityProperties);
            linkedEntity.AddForeignKey(propertiesFromEntity1, entity1.FindPrimaryKey(), entity1);
            linkedEntity.AddForeignKey(propertiesFromEntity2, entity2.FindPrimaryKey(), entity2);

            return(linkedEntity);
        }
Example #7
0
 public override int GetHashCode()
 {
     if (HashCode == 0)
     {
         HashCode = ResX.GetHashCode();
     }
     return(HashCode);
 }
Example #8
0
        /// <summary>
        ///     Adds a new alternate key to this entity type.
        /// </summary>
        /// <param name="properties"> The properties that make up the alternate key. </param>
        /// <returns> The newly created key. </returns>
        internal Key AddKey(IReadOnlyList <Property> properties)
        {
            Check.NotEmpty(properties, nameof(properties));
            Check.HasNoNulls(properties, nameof(properties));

            if (_baseType != null)
            {
                throw new InvalidOperationException(ResX.DerivedEntityKey(Name, _baseType.Name));
            }

            foreach (var property in properties)
            {
                if (FindProperty(property.Name) != property)
                {
                    throw new InvalidOperationException(ResX.KeyPropertiesWrongEntity(Property.Format(properties), Name));
                }

                if (property.ForeignKeys != null && property.ForeignKeys.Any(k => k.DeclaringEntity != this))
                {
                    throw new InvalidOperationException(ResX.KeyPropertyInForeignKey(property.Name, Name));
                }

                if (property.IsNullable)
                {
                    throw new InvalidOperationException(ResX.NullableKey(Name, property.Name));
                }
            }

            var key = FindKey(properties);

            if (key != null)
            {
                throw new InvalidOperationException(ResX.DuplicateKey(Property.Format(properties), Name, key.DeclaringEntity.Name));
            }

            key = new Key(properties);
            _keys.Add(properties, key);

            foreach (var property in properties)
            {
                var currentKeys = property.Keys;
                if (currentKeys == null)
                {
                    property.Keys = new Key[] { key };
                }
                else
                {
                    var newKeys = currentKeys.ToList();
                    newKeys.Add(key);
                    property.Keys = newKeys;
                }
            }

            return(Model.ConventionDispatcher.OnKeyAdded(key));
        }
Example #9
0
        public static string NullButNotEmpty(string value, string parameterName)
        {
            if (!ReferenceEquals(value, null) &&
                (value.Length == 0))
            {
                NotEmpty(parameterName, nameof(parameterName));

                throw new ArgumentException(ResX.ArgumentIsEmpty(parameterName));
            }

            return(value);
        }
Example #10
0
        public static T NotNull <T>(T value, string parameterName, string propertyName)
        {
            if (ReferenceEquals(value, null))
            {
                NotEmpty(parameterName, nameof(parameterName));
                NotEmpty(propertyName, nameof(propertyName));

                throw new ArgumentException(ResX.ArgumentPropertyNull(propertyName, parameterName));
            }

            return(value);
        }
Example #11
0
        /// <summary>
        ///     Adds an annotation to this object. Throws if an annotation with the specified name already exists.
        /// </summary>
        /// <param name="name"> The key of the annotation to be added. </param>
        /// <param name="annotation"> The annotation to be added. </param>
        /// <returns> The added annotation. </returns>
        public virtual Annotation AddAnnotation(string name, Annotation annotation)
        {
            var previousLength = _annotations.Value.Count;

            SetAnnotation(name, annotation);

            if (previousLength == _annotations.Value.Count)
            {
                throw new InvalidOperationException(ResX.DuplicateAnnotation(name));
            }

            return(annotation);
        }
Example #12
0
        /// <summary>
        ///     Gets the mapping that represents the given database type, throwing if no mapping is found.
        /// </summary>
        /// <param name="typeMapper"> The type mapper. </param>
        /// <param name="typeName"> The type to get the mapping for. </param>
        /// <returns> The type mapping to be used. </returns>
        public RelationalTypeMapping GetMapping(string typeName)
        {
            Check.NotNull(typeName, nameof(typeName));

            var mapping = FindMapping(typeName);

            if (mapping != null)
            {
                return(mapping);
            }

            throw new InvalidOperationException(ResX.UnsupportedType(typeName));
        }
Example #13
0
        /// <summary>
        ///     Gets the relational database type for a given .NET type, throwing if no mapping is found.
        /// </summary>
        /// <param name="typeMapper"> The type mapper. </param>
        /// <param name="clrType"> The type to get the mapping for. </param>
        /// <returns> The type mapping to be used. </returns>
        public RelationalTypeMapping GetMapping(Type clrType)
        {
            Check.NotNull(clrType, nameof(clrType));

            var mapping = FindMapping(clrType);

            if (mapping != null)
            {
                return(mapping);
            }

            throw new InvalidOperationException(ResX.UnsupportedType(clrType.ShortDisplayName()));
        }
Example #14
0
        /// <summary>
        ///     Gets the relational database type for a given property, throwing if no mapping is found.
        /// </summary>
        /// <param name="typeMapper"> The type mapper. </param>
        /// <param name="property"> The property to get the mapping for. </param>
        /// <returns> The type mapping to be used. </returns>
        public RelationalTypeMapping GetMapping(Property property)
        {
            Check.NotNull(property, nameof(property));

            var mapping = FindMapping(property);

            if (mapping != null)
            {
                return(mapping);
            }

            throw new InvalidOperationException(ResX.UnsupportedPropertyType(property.DeclaringEntity.Name, property.Name, property.ClrType.ShortDisplayName()));
        }
Example #15
0
        public static IReadOnlyList <T> NotEmpty <T>(IReadOnlyList <T> value, string parameterName)
        {
            NotNull(value, parameterName);

            if (value.Count == 0)
            {
                NotEmpty(parameterName, nameof(parameterName));

                throw new ArgumentException(ResX.CollectionArgumentIsEmpty(parameterName));
            }

            return(value);
        }
Example #16
0
        public ForeignKey(IReadOnlyList <Property> dependentProperties, Key principalKey, Entity dependentEntity, Entity principalEntity)
        {
            Check.NotEmpty(dependentProperties, nameof(dependentProperties));
            Check.HasNoNulls(dependentProperties, nameof(dependentProperties));
            Check.NotNull(principalKey, nameof(principalKey));
            Check.NotNull(principalEntity, nameof(principalEntity));

            Properties      = dependentProperties;
            PrincipalKey    = principalKey;
            DeclaringEntity = dependentEntity;
            PrincipalEntity = principalEntity;

            AreCompatible(principalKey.Properties, dependentProperties, principalEntity, dependentEntity, shouldThrow: true);

            if (!principalEntity.GetKeys().Contains(principalKey))
            {
                throw new InvalidOperationException(ResX.ForeignKeyReferencedEntityKeyMismatch(Property.Format(principalKey.Properties), principalEntity.Name));
            }
        }
Example #17
0
        private DbCommand CreateCommand(IRelationalConnection connection, IReadOnlyDictionary <string, object> parameterValues)
        {
            var command = connection.DbConnection.CreateCommand();

            command.CommandText = CommandText;

            if (connection.CurrentTransaction != null)
            {
                command.Transaction = connection.CurrentTransaction.GetDbTransaction();
            }

            if (connection.CommandTimeout != null)
            {
                command.CommandTimeout = (int)connection.CommandTimeout;
            }

            if (Parameters.Count > 0)
            {
                if (parameterValues == null)
                {
                    throw new InvalidOperationException(ResX.MissingParameterValue(Parameters[0].InvariantName));
                }

                foreach (var parameter in Parameters)
                {
                    object parameterValue;

                    if (parameterValues.TryGetValue(parameter.InvariantName, out parameterValue))
                    {
                        parameter.AddDbParameter(command, parameterValue);
                    }
                    else
                    {
                        throw new InvalidOperationException(ResX.MissingParameterValue(parameter.InvariantName));
                    }
                }
            }

            return(command);
        }
Example #18
0
        public static string NotEmpty(string value, string parameterName)
        {
            Exception e = null;

            if (ReferenceEquals(value, null))
            {
                e = new ArgumentNullException(parameterName);
            }
            else if (value.Trim().Length == 0)
            {
                e = new ArgumentException(ResX.ArgumentIsEmpty(parameterName));
            }

            if (e != null)
            {
                NotEmpty(parameterName, nameof(parameterName));

                throw e;
            }

            return(value);
        }
        public static void LogCommandExecuted(this ILogger logger, DbCommand command, long startTimestamp, long currentTimestamp)
        {
            Check.NotNull(logger, nameof(logger));
            Check.NotNull(command, nameof(command));

            if (logger.IsEnabled(LogLevel.Information))
            {
                var logParameterValues = command.Parameters.Count > 0;
                var parameters         = command.Parameters.Cast <DbParameter>().Select(p => new DbParameterLogData(p.ParameterName,
                                                                                                                    logParameterValues ? p.Value : "?",
                                                                                                                    logParameterValues,
                                                                                                                    p.Direction,
                                                                                                                    p.DbType,
                                                                                                                    p.IsNullable,
                                                                                                                    p.Size,
                                                                                                                    p.Precision,
                                                                                                                    p.Scale)).ToList();

                var logData = new DbCommandLogData(command.CommandText.TrimEnd(),
                                                   command.CommandType,
                                                   command.CommandTimeout,
                                                   parameters,
                                                   DeriveTimespan(startTimestamp, currentTimestamp));

                logger.Log(LogLevel.Information, (int)RelationalEventId.ExecutedCommand, logData, null, (state, _) =>
                {
                    var elapsedMilliseconds = DeriveTimespan(startTimestamp, currentTimestamp);

                    return(ResX.RelationalLoggerExecutedCommand(string.Format(CultureInfo.InvariantCulture, "{0:N0}", elapsedMilliseconds),
                                                                state.Parameters.Select(p => $"{p.Name}={p.FormatParameter()}").Join(), // Interpolation okay here because value is always a string.
                                                                state.CommandType,
                                                                state.CommandTimeout,
                                                                Environment.NewLine,
                                                                state.CommandText));
                });
            }
        }
Example #20
0
        public virtual void AddDbParameter(DbCommand command, object value)
        {
            Check.NotNull(command, nameof(command));
            Check.NotNull(value, nameof(value));

            var innerValues = value as object[];

            if (innerValues != null)
            {
                if (innerValues.Length < RelationalParameters.Count)
                {
                    throw new InvalidOperationException(ResX.MissingParameterValue(RelationalParameters[innerValues.Length].InvariantName));
                }

                for (var i = 0; i < RelationalParameters.Count; i++)
                {
                    RelationalParameters[i].AddDbParameter(command, innerValues[i]);
                }
            }
            else
            {
                throw new InvalidOperationException(ResX.ParameterNotObjectArray(InvariantName));
            }
        }
Example #21
0
        /// <summary>
        ///     Adds a new relationship to this entity.
        /// </summary>
        /// <param name="properties"> The properties that the foreign key is defined on. </param>
        /// <param name="principalKey"> The primary or alternate key that is referenced. </param>
        /// <param name="principalEntity">
        ///     The entity type that the relationship targets. This may be different from the type that <paramref name="principalKey" />
        ///     is defined on when the relationship targets a derived type in an inheritance hierarchy (since the key is defined on the
        ///     base type of the hierarchy).
        /// </param>
        /// <returns> The newly created foreign key. </returns>
        internal ForeignKey AddForeignKey(IReadOnlyList <Property> properties, Key principalKey, Entity principalEntity, bool runConventions = true)
        {
            Check.NotEmpty(properties, nameof(properties));
            Check.HasNoNulls(properties, nameof(properties));
            Check.NotNull(principalKey, nameof(principalKey));
            Check.NotNull(principalEntity, nameof(principalEntity));

            foreach (var property in properties)
            {
                var actualProperty = FindProperty(property.Name);
                if (actualProperty == null || !actualProperty.DeclaringEntity.IsAssignableFrom(property.DeclaringEntity))
                {
                    throw new InvalidOperationException(ResX.ForeignKeyPropertiesWrongEntity(Property.Format(properties), Name));
                }

                if (actualProperty.GetContainingKeys().Any(k => k.DeclaringEntity != this))
                {
                    throw new InvalidOperationException(ResX.ForeignKeyPropertyInKey(actualProperty.Name, Name));
                }
            }

            var duplicateForeignKey = FindForeignKeysInHierarchy(properties, principalKey, principalEntity).FirstOrDefault();

            if (duplicateForeignKey != null)
            {
                throw new InvalidOperationException(ResX.DuplicateForeignKey(Property.Format(properties), Name, duplicateForeignKey.DeclaringEntity.Name, Property.Format(principalKey.Properties), principalEntity.Name));
            }

            var foreignKey = new ForeignKey(properties, principalKey, this, principalEntity);

            _foreignKeys.Add(foreignKey);

            foreach (var property in properties)
            {
                var currentKeys = property.ForeignKeys;
                if (currentKeys == null)
                {
                    property.ForeignKeys = new ForeignKey[] { foreignKey };
                }
                else
                {
                    var newKeys = currentKeys.ToList();
                    newKeys.Add(foreignKey);
                    property.ForeignKeys = newKeys;
                }
            }

            if (principalKey.ReferencingForeignKeys == null)
            {
                principalKey.ReferencingForeignKeys = new List <ForeignKey> {
                    foreignKey
                };
            }
            else
            {
                principalKey.ReferencingForeignKeys.Add(foreignKey);
            }

            if (principalEntity.DeclaredReferencingForeignKeys == null)
            {
                principalEntity.DeclaredReferencingForeignKeys = new List <ForeignKey> {
                    foreignKey
                };
            }
            else
            {
                principalEntity.DeclaredReferencingForeignKeys.Add(foreignKey);
            }

            if (runConventions)
            {
                Model.ConventionDispatcher.OnForeignKeyAdded(foreignKey);
            }

            return(foreignKey);
        }