Esempio n. 1
0
        protected MetadataSchema GetMetadata()
        {
            if (_metadata == null)
            {
                lock (MetadataLock)
                {
                    if (!FactoryMetadata.TryGetValue(Session.SessionFactory, out _metadata))
                    {
                        var builder = new NHMetadataBuilder(Session.SessionFactory, _breezeConfig, _breezeConfigurator);
                        _metadata = builder.BuildMetadata(TypeFilter);
                        FactoryMetadata.Add(Session.SessionFactory, _metadata);
                        OnMetadataBuilt(_metadata);
                    }
                }
            }

            return(_metadata);
        }
Esempio n. 2
0
        /// <summary>
        /// Find out if a bidirectional relation exists, if exists then add entity to the collection
        /// </summary>
        /// <param name="manyToOneType">Many to one relation</param>
        /// <param name="childEntityType">Entity type of the child</param>
        /// <param name="propertyName">Property name of the ManyToOne realtion</param>
        /// <param name="childEntityInfo">Entity info of the child</param>
        /// <param name="childMeta">Child metadata</param>
        /// <returns>true if the child entity was added or removed from the parent entity collection, otherwise false</returns>
        private bool TryToFindAndLinkBidirectionalRelation(ManyToOneType manyToOneType,
                                                           EntityType childEntityType, string propertyName,
                                                           EntityInfo childEntityInfo, IClassMetadata childMeta)
        {
            var fk             = FindForeignKey(propertyName, childMeta);
            var parentMeta     = _session.SessionFactory.GetClassMetadata(manyToOneType.ReturnedClass);
            var propNames      = parentMeta.PropertyNames;
            var propTypes      = parentMeta.PropertyTypes;
            var childPersister = childMeta as AbstractEntityPersister;

            if (childPersister == null)
            {
                return(false);
            }
            var colProp = new Dictionary <string, string>();

            for (var i = 0; i < childPersister.PropertyNames.Length; i++)
            {
                var propName = childPersister.PropertyNames[i];
                var propType = childPersister.GetPropertyType(propName);
                if (propType.IsAssociationType)
                {
                    continue;
                }
                foreach (var col in childPersister.GetPropertyColumnNames(i))
                {
                    if (col == null)
                    {
                        continue; // formula
                    }
                    if (!colProp.ContainsKey(col))
                    {
                        colProp.Add(col, propName);
                    }
                }
            }
            if (childPersister.IdentifierType.IsComponentType)
            {
                var componentType = (ComponentType)childPersister.IdentifierType;
                for (var i = 0; i < componentType.PropertyNames.Length; i++)
                {
                    colProp.Add(childPersister.IdentifierColumnNames[i], componentType.PropertyNames[i]);
                }
            }
            else
            {
                foreach (var col in childPersister.IdentifierColumnNames)
                {
                    colProp.Add(col, childPersister.IdentifierPropertyName);
                }
            }


            for (var i = 0; i < propNames.Length; i++)
            {
                var propType = propTypes[i];
                var propName = propNames[i];
                if (!propType.IsAssociationType || !propType.IsCollectionType)
                {
                    continue;
                }
                var colType = (CollectionType)propType;

                var refCols  = colType.GetReferencedColumns(_session.GetSessionImplementation().Factory);
                var refProps = refCols.Select(refCol => !colProp.ContainsKey(refCol) ? refCol : colProp[refCol]).ToArray();
                if (NHMetadataBuilder.CatColumnNames(refProps) != fk)
                {
                    continue;
                }

                var elmType = colType.GetElementType(_session.GetSessionImplementation().Factory);
                if (!elmType.ReturnedClass.IsAssignableFrom(childMeta.MappedClass))
                {
                    continue;
                }

                var parentEntity = GetRelatedEntity(propertyName, childEntityType, childEntityInfo, childMeta);
                if (parentEntity == null)
                {
                    return(false);
                }

                var coll = parentMeta.GetPropertyValue(parentEntity, propName) as IEnumerable;

                if (coll == null) //Should happen only if the parent entity is not in db
                {
                    //TODO: instantiate collection
                    continue;
                }
                var collType = coll.GetType();

                //Initialize collection in order to prevent flushing
                if (!NHibernateUtil.IsInitialized(coll))
                {
                    NHibernateUtil.Initialize(coll);
                }

                if (colType.ReturnedClass.IsGenericType)
                {
                    var state = childEntityInfo.EntityState;
                    if (_saveMap.ContainsKey(manyToOneType.ReturnedClass))
                    {
                        var parentEntityInfo =
                            _saveMap[manyToOneType.ReturnedClass].FirstOrDefault(o => o.Entity == parentEntity);
                        if (parentEntityInfo != null)
                        {
                            switch (parentEntityInfo.EntityState)
                            {
                            case EntityState.Added:
                                //if the parent is added then we need to add child to the collection even if the it is only updated or unmodified
                                if (state != EntityState.Deleted)
                                {
                                    state = EntityState.Added;
                                }
                                break;

                            case EntityState.Deleted:
                                //TODO: check for cascade option
                                break;

                            case EntityState.Modified:
                                break;
                            }
                        }
                    }

                    //TODO: check if parent is new
                    switch (state)
                    {
                    case EntityState.Deleted:
                        var removeMethod = collType.GetMethod("Remove") ??
                                           collType.GetInterfaces()
                                           .Select(o => o.GetMethod("Remove"))
                                           .FirstOrDefault(o => o != null);
                        var removed = false;
                        if (removeMethod != null)
                        {
                            IEqualityComparer comparer = new EntityComparer(childMeta);

                            foreach (var item in coll)
                            {
                                if (comparer.Equals(item, childEntityInfo.Entity))
                                {
                                    removed = (bool)removeMethod.Invoke(coll, new[] { item });
                                    break;
                                }
                            }
                        }
                        childMeta.SetPropertyValue(childEntityInfo.Entity, propertyName, null);    //Remove relation on both sides
                        return(removed);

                    case EntityState.Added:
                        var addMethod = collType.GetMethod("Add") ??
                                        collType.GetInterfaces()
                                        .Select(o => o.GetMethod("Add"))
                                        .FirstOrDefault(o => o != null);
                        if (addMethod != null)
                        {
                            addMethod.Invoke(coll, new[] { childEntityInfo.Entity });
                            return(true);
                        }
                        break;
                    }
                }
                //TODO: non generic collections
            }
            return(false);
        }