Exemplo n.º 1
0
        /// <summary>
        /// Loads a foreign key property.
        /// </summary>
        /// <param name="property">The property.</param>
        /// <param name="connection">The connection.</param>
        /// <remarks></remarks>
        internal object LoadForeign(System.Reflection.PropertyInfo property, ConnectionStringSettings connection)
        {
            if (!propertyData.ContainsKey(property.Name))
            {
                ForeignKeyInfo field = ForeignKeyInfo.Create(property);
                if (field == null)
                {
                    throw new Tenor.Data.MissingFieldException(property.DeclaringType, property.Name);
                }

                /*
                 * Dim filters As String = ""
                 * Dim params As New List(Of Data.Parameter)
                 */
                TableInfo table = TableInfo.CreateTableInfo(field.ElementType);
                if (connection == null)
                {
                    connection = table.GetConnection();
                }


                if (!field.IsArray && table.Cacheable)
                {
                    //We found a cacheble instance, so we don't need to search.
                    EntityBase instance = (EntityBase)Activator.CreateInstance(table.RelatedTable);
                    for (int i = 0; i <= field.ForeignFields.Length - 1; i++)
                    {
                        field.ForeignFields[i].SetPropertyValue(instance, field.LocalFields[i].PropertyValue(this));
                    }
                    instance.Bind();
                    field.SetPropertyValue(this, instance);
                    return(instance);
                }

                EntityBase[] instances;
                if (lazyEnabled)
                {
                    SearchOptions sc = new SearchOptions(field.ElementType);

                    bool fkHasValue = false;

                    if (field.IsManyToMany)
                    {
                        Join j = new Join(GeneralDialect.ManyToManyAlias);
                        j.ForeignKey     = field;
                        j.LocalTableInfo = table;
                        sc.Conditions.includes.Add(j);

                        for (int i = 0; i <= field.ForeignFields.Length - 1; i++)
                        {
                            if (i > 0)
                            {
                                sc.Conditions.Add(Tenor.Data.LogicalOperator.And);
                            }
                            SearchConditionForManyToMany scmm = new SearchConditionForManyToMany(
                                GeneralDialect.ManyToManyAlias,
                                field.LocalManyToManyFields[i],
                                field.LocalFields[i].PropertyValue(this));

                            sc.Conditions.Add(scmm);

                            fkHasValue = true;
                        }
                    }
                    else
                    {
                        //lets find objects, one-to-many and many-to-one
                        //for each Foreign, join an AND operator to match foreign with local value.

                        if (field.ForeignFields.Length != field.LocalFields.Length)
                        {
                            throw new MissingForeignKeyException(this.GetType(), property.Name);
                        }

                        for (int i = 0; i <= field.ForeignFields.Length - 1; i++)
                        {
                            if (i > 0)
                            {
                                sc.Conditions.Add(Tenor.Data.LogicalOperator.And);
                            }

                            object value = field.LocalFields[i].PropertyValue(this);

                            // only one fk field needs to have a value set
                            fkHasValue = fkHasValue || (value != null && value != DBNull.Value);

                            sc.Conditions.Add(
                                /* the foreign property name */
                                field.ForeignFields[i].RelatedProperty.Name,
                                /* the local value */
                                value);
                        }

                        if (sc.Conditions.Count == 0)
                        {
                            //this should never happen.
                            throw (new TenorException());
                        }
                    }

                    // lazy is enabled, go database, go!

                    // only searches if fk field is not null
                    if (fkHasValue)
                    {
                        instances = sc.Execute(connection);
                    }
                    else
                    {
                        instances = new EntityBase[] { }
                    };
                }
                else
                {
                    //lazy is disabled, so, no data will be retrieved.
                    instances = new EntityBase[] { };
                }


                if (field.IsArray)
                {
                    if (field.RelatedProperty.PropertyType.IsArray)
                    {
                        propertyData.Add(property.Name, instances);
                    }
                    else
                    {
                        // There must be another way to create it, string is not cool.
                        Type listof = Type.GetType("Tenor.Data.EntityList`1[[" + field.ElementType.AssemblyQualifiedName + "]]");
                        System.Reflection.ConstructorInfo ctor = listof.GetConstructor(System.Reflection.BindingFlags.CreateInstance | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic, null, new Type[] { typeof(EntityBase), typeof(string) }, null);
                        IList obj = (IList)ctor.Invoke(new object[] { (EntityBase)this, property.Name });
                        obj.Clear();
                        foreach (EntityBase i in instances)
                        {
                            obj.Add(i);
                        }
                        propertyData.Add(property.Name, obj);
                    }
                }
                else
                {
                    if (instances.Length == 0)
                    {
                        propertyData.Add(property.Name, null);
                    }
                    else
                    {
                        if (instances.Length > 1)
                        {
                            throw new ManyRecordsFoundException();//"LoadingForeignKey-ManyToOne: More than one instance was returned");
                        }
                        propertyData.Add(property.Name, instances[0]);
                    }
                }
            }
            return(propertyData[property.Name]);
        }