Exemple #1
0
        private static void GetOneToManyChildren <T>(this SQLiteConnection conn, ref T element,
                                                     PropertyInfo relationshipProperty)
        {
            var          type = typeof(T);
            EnclosedType enclosedType;
            var          entityType = relationshipProperty.GetEntityType(out enclosedType);

            Debug.Assert(enclosedType != EnclosedType.None, "OneToMany relationship must be a List or Array");

            var currentEntityPrimaryKeyProperty = type.GetPrimaryKey();

            Debug.Assert(currentEntityPrimaryKeyProperty != null, "OneToMany relationship origin must have Primary Key");

            var otherEntityForeignKeyProperty = type.GetForeignKeyProperty(relationshipProperty, inverse: true);

            Debug.Assert(otherEntityForeignKeyProperty != null,
                         "OneToMany relationship destination must have Foreign Key to the origin class");
            var tableMapping = conn.GetMapping(entityType);

            Debug.Assert(tableMapping != null, "There's no mapping table for OneToMany relationship destination");

            var inverseProperty = type.GetInverseProperty(relationshipProperty);

            IEnumerable values          = null;
            var         primaryKeyValue = currentEntityPrimaryKeyProperty.GetValue(element, null);

            if (primaryKeyValue != null)
            {
                var query = string.Format("SELECT * FROM [{0}] WHERE [{1}] = ?", entityType.GetTableName(),
                                          otherEntityForeignKeyProperty.GetColumnName());

                var softDeleteSql = GetSoftDeleteFilterSql(entityType);

                if (softDeleteSql != null)
                {
                    query = String.Concat(query, " AND ", softDeleteSql);
                }

                var queryResults = conn.Query(tableMapping, query, primaryKeyValue is Guid ? primaryKeyValue.ToString() : primaryKeyValue);

                values = CreateEnclosedType(entityType, enclosedType, queryResults);
            }

            relationshipProperty.SetValue(element, values, null);

            if (inverseProperty != null && values != null)
            {
                // Establish inverse relationships (we already have that object anyway)
                foreach (var value in values)
                {
                    inverseProperty.SetValue(value, element, null);
                }
            }
        }
Exemple #2
0
        private static void GetManyToManyChildren <T>(this SQLiteConnection conn, ref T element,
                                                      PropertyInfo relationshipProperty)
        {
            var          type = typeof(T);
            EnclosedType enclosedType;
            var          entityType = relationshipProperty.GetEntityType(out enclosedType);

            var currentEntityPrimaryKeyProperty = type.GetPrimaryKey();
            var otherEntityPrimaryKeyProperty   = entityType.GetPrimaryKey();
            var manyToManyMetaInfo = type.GetManyToManyMetaInfo(relationshipProperty);
            var currentEntityForeignKeyProperty = manyToManyMetaInfo.OriginProperty;
            var otherEntityForeignKeyProperty   = manyToManyMetaInfo.DestinationProperty;
            var intermediateType = manyToManyMetaInfo.IntermediateType;
            var tableMapping     = conn.GetMapping(entityType);

            Debug.Assert(enclosedType != EnclosedType.None, "ManyToMany relationship must be a List or Array");
            Debug.Assert(currentEntityPrimaryKeyProperty != null, "ManyToMany relationship origin must have Primary Key");
            Debug.Assert(otherEntityPrimaryKeyProperty != null, "ManyToMany relationship destination must have Primary Key");
            Debug.Assert(intermediateType != null, "ManyToMany relationship intermediate type cannot be null");
            Debug.Assert(currentEntityForeignKeyProperty != null, "ManyToMany relationship origin must have a foreign key defined in the intermediate type");
            Debug.Assert(otherEntityForeignKeyProperty != null, "ManyToMany relationship destination must have a foreign key defined in the intermediate type");
            Debug.Assert(tableMapping != null, "There's no mapping table defined for ManyToMany relationship origin");

            IEnumerable values          = null;
            var         primaryKeyValue = currentEntityPrimaryKeyProperty.GetValue(element, null);

            if (primaryKeyValue != null)
            {
                // Obtain the relationship keys
                var keysQuery = string.Format("SELECT [{0}] FROM [{1}] WHERE [{2}] = ?", otherEntityForeignKeyProperty.Name,
                                              intermediateType.Name, currentEntityForeignKeyProperty.Name);

                var query = string.Format("SELECT * FROM [{0}] WHERE [{1}] IN ({2})", entityType.Name,
                                          otherEntityPrimaryKeyProperty.Name, keysQuery);

                var queryResults = conn.Query(tableMapping, query, primaryKeyValue);

                values = CreateEnclosedType(entityType, enclosedType, queryResults);
            }

            relationshipProperty.SetValue(element, values, null);
        }
Exemple #3
0
        private static void GetManyToOneChild <T>(this SQLiteConnection conn, ref T element,
                                                  PropertyInfo relationshipProperty)
        {
            var          type = typeof(T);
            EnclosedType enclosedType;
            var          entityType = relationshipProperty.GetEntityType(out enclosedType);

            Debug.Assert(enclosedType == EnclosedType.None, "ManyToOne relationship cannot be of type List or Array");

            var otherEntityPrimaryKeyProperty = entityType.GetPrimaryKey();

            Debug.Assert(otherEntityPrimaryKeyProperty != null,
                         "ManyToOne relationship destination must have Primary Key");

            var currentEntityForeignKeyProperty = type.GetForeignKeyProperty(relationshipProperty);

            Debug.Assert(currentEntityForeignKeyProperty != null, "ManyToOne relationship origin must have Foreign Key");

            var tableMapping = conn.GetMapping(entityType);

            Debug.Assert(tableMapping != null, "There's no mapping table for OneToMany relationship destination");

            object value           = null;
            var    foreignKeyValue = currentEntityForeignKeyProperty.GetValue(element, null);

            if (foreignKeyValue != null)
            {
                value = conn.Find(foreignKeyValue, tableMapping);

                if (IsSoftDeleted(entityType, value))
                {
                    value = null;
                }
            }

            relationshipProperty.SetValue(element, value, null);
        }
        private static void UpdateManyToManyForeignKeys(this SQLiteConnection conn, object element, PropertyInfo relationshipProperty)
        {
            var type = element.GetType();

            EnclosedType enclosedType;
            var          entityType = relationshipProperty.GetEntityType(out enclosedType);

            var currentEntityPrimaryKeyProperty = type.GetPrimaryKey();
            var otherEntityPrimaryKeyProperty   = entityType.GetPrimaryKey();
            var manyToManyMetaInfo = type.GetManyToManyMetaInfo(relationshipProperty);
            var currentEntityForeignKeyProperty = manyToManyMetaInfo.OriginProperty;
            var otherEntityForeignKeyProperty   = manyToManyMetaInfo.DestinationProperty;
            var intermediateType = manyToManyMetaInfo.IntermediateType;

            Assert(enclosedType != EnclosedType.None, type, relationshipProperty, "ManyToMany relationship must be a List or Array");
            Assert(currentEntityPrimaryKeyProperty != null, type, relationshipProperty, "ManyToMany relationship origin must have Primary Key");
            Assert(otherEntityPrimaryKeyProperty != null, type, relationshipProperty, "ManyToMany relationship destination must have Primary Key");
            Assert(intermediateType != null, type, relationshipProperty, "ManyToMany relationship intermediate type cannot be null");
            Assert(currentEntityForeignKeyProperty != null, type, relationshipProperty, "ManyToMany relationship origin must have a foreign key defined in the intermediate type");
            Assert(otherEntityForeignKeyProperty != null, type, relationshipProperty, "ManyToMany relationship destination must have a foreign key defined in the intermediate type");

            var primaryKey = currentEntityPrimaryKeyProperty.GetValue(element, null);

            // Obtain the list of children keys
            var childList    = (IEnumerable)relationshipProperty.GetValue(element, null);
            var childKeyList = (from object child in childList ?? new List <object>()
                                select otherEntityPrimaryKeyProperty.GetValue(child, null)).ToList();

            // Check for already existing relationships
            var childrenPlaceHolders = string.Join(",", Enumerable.Repeat("?", childKeyList.Count));
            var currentChildrenQuery = string.Format("select [{0}] from [{1}] where [{2}] == ? and [{0}] in ({3})",
                                                     otherEntityForeignKeyProperty.GetColumnName(), intermediateType.GetTableName(), currentEntityForeignKeyProperty.GetColumnName(), childrenPlaceHolders);
            var parameters = new List <object> {
                primaryKey
            };

            parameters.AddRange(childKeyList);
            var currentChildKeyList =
                from object child in conn.Query(conn.GetMapping(intermediateType), currentChildrenQuery, parameters.ToArray())
                select otherEntityForeignKeyProperty.GetValue(child, null);


            // Insert missing relationships in the intermediate table
            var missingChildKeyList        = childKeyList.Where(o => !currentChildKeyList.Contains(o)).ToList();
            var missingIntermediateObjects = new List <object>(missingChildKeyList.Count);

            foreach (var missingChildKey in missingChildKeyList)
            {
                var intermediateObject = Activator.CreateInstance(intermediateType);
                currentEntityForeignKeyProperty.SetValue(intermediateObject, primaryKey, null);
                otherEntityForeignKeyProperty.SetValue(intermediateObject, missingChildKey, null);

                missingIntermediateObjects.Add(intermediateObject);
            }

            conn.InsertAll(missingIntermediateObjects);

            // Delete any other pending relationship
            var deleteQuery = string.Format("delete from [{0}] where [{1}] == ? and [{2}] not in ({3})",
                                            intermediateType.GetTableName(), currentEntityForeignKeyProperty.GetColumnName(),
                                            otherEntityForeignKeyProperty.GetColumnName(), childrenPlaceHolders);

            conn.Execute(deleteQuery, parameters.ToArray());
        }
Exemple #5
0
        private static void GetOneToManyChildren <T>(this SQLiteConnection conn, ICollection <T> elements, PropertyInfo relationshipProperty)
        {
            if (!elements.Any())
            {
                return;
            }

            var          type = typeof(T);
            EnclosedType enclosedType;
            var          entityType = relationshipProperty.GetEntityType(out enclosedType);

            Debug.Assert(enclosedType != EnclosedType.None, "OneToMany relationship must be a List or Array");

            var currentEntityPrimaryKeyProperty = type.GetPrimaryKey();

            Debug.Assert(currentEntityPrimaryKeyProperty != null, "OneToMany relationship origin must have Primary Key");

            var otherEntityForeignKeyProperty = type.GetForeignKeyProperty(relationshipProperty, inverse: true);

            Debug.Assert(otherEntityForeignKeyProperty != null,
                         "OneToMany relationship destination must have Foreign Key to the origin class");

            var tableMapping = conn.GetMapping(entityType);

            Debug.Assert(tableMapping != null, "There's no mapping table for OneToMany relationship destination");

            var inverseProperty = type.GetInverseProperty(relationshipProperty);

            var primaryKeyValues = elements.Select(x => {
                var fkPropVal = currentEntityPrimaryKeyProperty.GetValue(x, null);

                return(fkPropVal is Guid ? fkPropVal.ToString() : fkPropVal);
            }).Where(x => x != null).Distinct().ToList();

            if (primaryKeyValues.Count == 0)
            {
                return;
            }

            var query = String.Format(
                "SELECT * FROM [{0}] WHERE [{1}] IN ({2})",
                entityType.GetTableName(),
                otherEntityForeignKeyProperty.GetColumnName(),
                String.Join(",", primaryKeyValues.Select(x => "?"))
                );

            var softDeleteSql = GetSoftDeleteFilterSql(entityType);

            if (softDeleteSql != null)
            {
                query = String.Concat(query, " AND ", softDeleteSql);
            }

            var children = conn.Query(
                tableMapping,
                query,
                primaryKeyValues.ToArray()
                );

            foreach (var element in elements)
            {
                var primaryKeyValue = currentEntityPrimaryKeyProperty.GetValue(element, null);

                var queryResults = children.Where(x => otherEntityForeignKeyProperty.GetValue(x, null).Equals(primaryKeyValue)).ToList();

                IEnumerable values = null;

                if (primaryKeyValue != null)
                {
                    values = CreateEnclosedType(entityType, enclosedType, queryResults);
                }

                relationshipProperty.SetValue(element, values, null);

                if (inverseProperty != null && values != null)
                {
                    // Establish inverse relationships (we already have that object anyway)
                    foreach (var value in values)
                    {
                        inverseProperty.SetValue(value, element, null);
                    }
                }
            }
        }
Exemple #6
0
        private static void GetManyToOneChildren <T>(this SQLiteConnection conn, ICollection <T> elements, PropertyInfo relationshipProperty) where T : new()
        {
            if (!elements.Any())
            {
                return;
            }

            var          type = typeof(T);
            EnclosedType enclosedType;
            var          entityType = relationshipProperty.GetEntityType(out enclosedType);

            Debug.Assert(enclosedType == EnclosedType.None, "ManyToOne relationship cannot be of type List or Array");

            var otherEntityPrimaryKeyProperty = entityType.GetPrimaryKey();

            Debug.Assert(otherEntityPrimaryKeyProperty != null,
                         "ManyToOne relationship destination must have Primary Key");

            var currentEntityForeignKeyProperty = type.GetForeignKeyProperty(relationshipProperty);

            Debug.Assert(currentEntityForeignKeyProperty != null, "ManyToOne relationship origin must have Foreign Key");

            var tableMapping = conn.GetMapping(entityType);

            Debug.Assert(tableMapping != null, "There's no mapping table for OneToMany relationship destination");

            var foreignKeyValues = elements.Select(x => {
                var fkPropVal = currentEntityForeignKeyProperty.GetValue(x, null);

                return(fkPropVal is Guid ? fkPropVal.ToString() : fkPropVal);
            }).Where(x => x != null).Distinct().ToList();

            if (foreignKeyValues.Count == 0)
            {
                return;
            }

            var query = String.Format(
                "SELECT * FROM \"{0}\" WHERE \"{1}\" IN ({2})",
                tableMapping.TableName,
                otherEntityPrimaryKeyProperty.GetColumnName(),
                String.Join(",", foreignKeyValues.Select(x => "?"))
                );

            var softDeleteSql = GetSoftDeleteFilterSql(entityType);

            if (softDeleteSql != null)
            {
                query = String.Concat(query, " AND ", softDeleteSql);
            }

            var foreignValues = conn.Query(
                tableMapping,
                query,
                foreignKeyValues.ToArray()
                );

            foreach (var element in elements)
            {
                var    foreignKeyValue = currentEntityForeignKeyProperty.GetValue(element, null);
                object value           = null;

                if (foreignKeyValue != null)
                {
                    value = foreignValues.SingleOrDefault(x => otherEntityPrimaryKeyProperty.GetValue(x, null).Equals(foreignKeyValue));
                }

                relationshipProperty.SetValue(element, value, null);
            }
        }
Exemple #7
0
        private static void GetOneToOneChild <T>(this SQLiteConnection conn, ref T element,
                                                 PropertyInfo relationshipProperty)
        {
            var          type = typeof(T);
            EnclosedType enclosedType;
            var          entityType = relationshipProperty.GetEntityType(out enclosedType);

            Debug.Assert(enclosedType == EnclosedType.None, "OneToOne relationship cannot be of type List or Array");

            var currentEntityPrimaryKeyProperty = type.GetPrimaryKey();
            var otherEntityPrimaryKeyProperty   = entityType.GetPrimaryKey();

            Debug.Assert(currentEntityPrimaryKeyProperty != null || otherEntityPrimaryKeyProperty != null,
                         "At least one entity in a OneToOne relationship must have Primary Key");

            var currentEntityForeignKeyProperty = type.GetForeignKeyProperty(relationshipProperty);
            var otherEntityForeignKeyProperty   = type.GetForeignKeyProperty(relationshipProperty, inverse: true);

            Debug.Assert(currentEntityForeignKeyProperty != null || otherEntityForeignKeyProperty != null,
                         "At least one entity in a OneToOne relationship must have Foreign Key");

            var hasForeignKey        = otherEntityPrimaryKeyProperty != null && currentEntityForeignKeyProperty != null;
            var hasInverseForeignKey = currentEntityPrimaryKeyProperty != null && otherEntityForeignKeyProperty != null;

            Debug.Assert(hasForeignKey || hasInverseForeignKey,
                         "Missing either ForeignKey or PrimaryKey for a complete OneToOne relationship");

            var tableMapping = conn.GetMapping(entityType);

            Debug.Assert(tableMapping != null, "There's no mapping table for OneToOne relationship");

            var inverseProperty = type.GetInverseProperty(relationshipProperty);

            object value = null;

            if (hasForeignKey)
            {
                var foreignKeyValue = currentEntityForeignKeyProperty.GetValue(element, null);
                if (foreignKeyValue != null)
                {
                    value = conn.Find(foreignKeyValue, tableMapping);
                }
            }
            else
            {
                var primaryKeyValue = currentEntityPrimaryKeyProperty.GetValue(element, null);
                if (primaryKeyValue != null)
                {
                    var query = string.Format("SELECT * FROM [{0}] WHERE [{1}] = ? LIMIT 1", entityType.Name,
                                              otherEntityForeignKeyProperty.Name);
                    value = conn.Query(tableMapping, query, primaryKeyValue).FirstOrDefault();
                    // Its a OneToOne, take only the first
                }
            }

            relationshipProperty.SetValue(element, value, null);

            if (value != null && inverseProperty != null)
            {
                inverseProperty.SetValue(value, element, null);
            }
        }