/// <summary>
        /// Specifies the related objects to include in the query results using
        /// a lambda expression listing the path members.
        /// </summary>
        /// <returns>A new System.Data.Objects.ObjectQuery&lt;T&gt; with the defined query path.</returns>
        public static IQueryable <T> Include <T>(this IQueryable <T> query, Expression <Func <T, object> > path)
        {
            // If it's a System.Data.Objects.ObjectQuery, apply the include, otherwise ignore:
            if (query is ObjectQuery <T> )
            {
                // Retrieve member path:
                List <ExtendedPropertyInfo> members = new List <ExtendedPropertyInfo>();
                EntityFrameworkHelper.CollectRelationalMembers(path, members);

                // Build string path:
                StringBuilder sb        = new StringBuilder();
                string        separator = "";
                foreach (ExtendedPropertyInfo member in members)
                {
                    if (member.ReferenceOnly)
                    {
                        break;
                    }
                    sb.Append(separator);
                    sb.Append(member.PropertyInfo.Name);
                    separator = ".";
                }

                // Apply Include:
                if (sb.Length > 0)
                {
                    return(((ObjectQuery <T>)query).Include(sb.ToString()));
                }
                else
                {
                    return(query);
                }
            }
            else
            {
                // Object is not an EF ObjectQuery:
                return(query);
            }
        }
Exemple #2
0
        /// <summary>
        /// Attaches multiple entire objectgraphs to the context.
        /// </summary>
        public static T[] AttachObjectGraphs <T>(this ObjectContext context, IEnumerable <T> entities, params Expression <Func <T, object> >[] paths)
        {
            T[]  unattachedEntities = entities.ToArray();
            T[]  attachedEntities   = new T[unattachedEntities.Length];
            Type entityType         = typeof(T);

            if (unattachedEntities.Length > 0)
            {
                // Workaround to ensure the assembly containing the entity type is loaded:
                // (see: https://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=3405138&SiteID=1)
                try { context.MetadataWorkspace.LoadFromAssembly(entityType.Assembly); }
                catch { }

                #region Automatic preload root entities

                // Create a WHERE clause for preload the root entities:
                StringBuilder where = new StringBuilder("(1=0)");
                List <ObjectParameter> pars = new List <ObjectParameter>();
                int pid = 0;
                foreach (T entity in unattachedEntities)
                {
                    // If the entity has an entitykey:
                    EntityKey entityKey = ((IEntityWithKey)entity).EntityKey;
                    if (entityKey != null)
                    {
                        where.Append(" OR ((1=1)");
                        foreach (EntityKeyMember keymember in entityKey.EntityKeyValues)
                        {
                            string pname = String.Format("p{0}", pid++);
                            where.Append(" AND (it.[");
                            where.Append(keymember.Key);
                            where.Append("] = @");
                            where.Append(pname);
                            where.Append(")");
                            pars.Add(new ObjectParameter(pname, keymember.Value));
                        }
                        where.Append(")");
                    }
                }

                // If WHERE clause not empty, construct and execute query:
                if (pars.Count > 0)
                {
                    // Construct query:
                    ObjectQuery <T> query = (ObjectQuery <T>)context.PublicGetProperty(context.GetEntitySetName(typeof(T)));
                    foreach (var path in paths)
                    {
                        query = (ObjectQuery <T>)query.Include(path);
                    }
                    query = query.Where(where.ToString(), pars.ToArray());

                    // Execute query and load entities:
                    //Console.WriteLine(query.ToTraceString());
                    query.Execute(MergeOption.AppendOnly).ToArray();
                }

                #endregion Automatic preload root entities

                // Attach the root entities:
                for (int i = 0; i < unattachedEntities.Length; i++)
                {
                    attachedEntities[i] = (T)context.AddOrAttachInstance(unattachedEntities[i], true);
                }

                // Collect property paths into a tree:
                TreeNode <ExtendedPropertyInfo> root = new TreeNode <ExtendedPropertyInfo>(null);
                foreach (var path in paths)
                {
                    List <ExtendedPropertyInfo> members = new List <ExtendedPropertyInfo>();
                    EntityFrameworkHelper.CollectRelationalMembers(path, members);
                    root.AddPath(members);
                }

                // Navigate over all properties:
                for (int i = 0; i < unattachedEntities.Length; i++)
                {
                    NavigatePropertySet(context, root, unattachedEntities[i], attachedEntities[i]);
                }
            }

            // Return the attached root entities:
            return(attachedEntities);
        }