Ejemplo n.º 1
0
        public void MapAndDefaultIncludesAttribute()
        {
            _expander = new Expander();
            var config = new PopcornConfiguration(_expander);

            Assert.ThrowsException <MultipleDefaultsException>(() => config.Map <RootObject, IncludeByDefaultRootObjectProjection>($"[{nameof(IncludeByDefaultRootObjectProjection.Id)},{nameof(IncludeByDefaultRootObjectProjection.StringValue)}]"));
        }
Ejemplo n.º 2
0
        public void DefaultIncludesAttribute()
        {
            _expander = new Expander();
            var config = new PopcornConfiguration(_expander);

            config.Map <RootObject, IncludeByDefaultRootObjectProjection>();

            var root = new RootObject
            {
                Id                     = Guid.NewGuid(),
                StringValue            = "Name",
                NonIncluded            = "A description",
                ExcludedFromProjection = "Some Details",
                Child                  = new ChildObject
                {
                    Id          = Guid.NewGuid(),
                    Name        = "Name",
                    Description = "Description"
                }
            };

            var result = _expander.Expand(root);

            result.ShouldNotBeNull();

            IncludeByDefaultRootObjectProjection projection = result as IncludeByDefaultRootObjectProjection;

            projection.ShouldNotBeNull();
            projection.StringValue.ShouldBe(root.StringValue);
            projection.Id.ShouldBe(root.Id);

            projection.NonIncluded.ShouldBeNull();
            projection.Child.ShouldBeNull();
        }
Ejemplo n.º 3
0
        public void SetupExpanderRegistry()
        {
            _expander = new Expander();
            var config = new PopcornConfiguration(_expander);

            config.Map <UserRelationship, UserRelationship>(config: builder =>
            {
                builder.AlternativeMap <UserRelationshipNameProjection>();
                builder.AlternativeMap <UserRelationshipEmailProjection>();
                builder.AlternativeMap <UserRelationshipMixedProjection>();
            });
            config.Map <User, UserFullProjection>(config: builder =>
            {
                builder.AlternativeMap <UserWithNameProjection>();
                builder.AlternativeMap <UserWithEmailProjection>();
            });
            config.Map <UserCollection, UserCollectionProjection>();
        }
Ejemplo n.º 4
0
        public void SetupExpanderRegistry()
        {
            _expander = new Expander();
            var config = new PopcornConfiguration(_expander);

            config.Map <RootObject, RootObjectProjection>($"[{nameof(RootObjectProjection.Id)},{nameof(RootObjectProjection.StringValue)},{nameof(RootObjectProjection.NonIncluded)}]",
                                                          (definition) =>
            {
                definition.Translate(o => o.ValueFromTranslator, () => 5.2);
                definition.Translate(o => o.ComplexFromTranslator, () => new ChildObjectProjection {
                    Id = new Guid(), Name = "Complex trans name", Description = "Complex trans description"
                });
            });

            config.Map <ChildObject, ChildObjectProjection>();
            config.Map <DerivedChildObject, DerivedChildObjectProjection>();
            config.Map <Loop, LoopProjection>();
            config.Map <EntityFromFactory, EntityFromFactoryProjection>();
            config.AssignFactory <EntityFromFactoryProjection>(() => new EntityFromFactoryProjection {
                ShouldBeEmpty = "Generated"
            });
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Helper function creating a mapping from a source type to a destination type.  Will attempt to auto-load navigation properties as needed.
        /// </summary>
        /// <param name="optionsBuilder"></param>
        /// <param name="defaultIncludes"></param>
        /// <param name="self">todo: describe self parameter on MapEntityFramework</param>
        /// <typeparam name="TSourceType"></typeparam>
        /// <typeparam name="TDestType"></typeparam>
        /// <typeparam name="TContext"></typeparam>
        /// <returns></returns>
        public static PopcornConfiguration MapEntityFramework <TSourceType, TDestType, TContext>(
            this PopcornConfiguration self,
            DbContextOptionsBuilder <TContext> optionsBuilder,
            string defaultIncludes = null)
            where TContext : DbContext
            where TSourceType : class
            where TDestType : class
        {
            return(self.Map <TSourceType, TDestType>(defaultIncludes, (definition) =>
            {
                definition
                // Before dealing with this object, create a context to use
                .BeforeExpansion((destinationObject, sourceObject, context) =>
                {
                    // Do some reference counting here
                    if (!context.ContainsKey(DbKey))
                    {
                        DbContext db = ConstructDbContextWithOptions(optionsBuilder);
                        try
                        {
                            db.Attach(sourceObject);
                            context[DbKey] = db;
                            context[DbCountKey] = 1;
                        }
                        catch { }
                    }
                    else
                    {
                        context[DbCountKey] = (int)context[DbCountKey] + 1;
                    }
                })
                // Afterwards clean up our resources
                .AfterExpansion((destinationObject, sourceObject, context) =>
                {
                    if (context.ContainsKey(DbKey))
                    {
                        // If the reference count goes to 0, destroy the context
                        var decrementedReferenceCount = (int)context[DbCountKey] - 1;
                        if (decrementedReferenceCount == 0)
                        {
                            (context[DbKey] as IDisposable).Dispose();
                            context.Remove(DbKey);
                            context.Remove(DbCountKey);
                        }
                        else
                        {
                            context[DbCountKey] = decrementedReferenceCount;
                        }
                    }
                });

                // Now, find all navigation properties on this type and configure each one to load from the database if
                // actually requested for expansion
                using (DbContext db = ConstructDbContextWithOptions(optionsBuilder))
                {
                    foreach (var prop in typeof(TSourceType).GetNavigationReferenceProperties(db))
                    {
                        definition.PrepareProperty(prop.Name, (destinationObject, destinationProperty, sourceObject, context) =>
                        {
                            if (context.ContainsKey(DbKey))
                            {
                                var expandDb = context[DbKey] as TContext;
                                expandDb.Attach(sourceObject as TSourceType);
                                expandDb.Entry(sourceObject as TSourceType).Reference(prop.Name).Load();
                            }
                        });
                    }

                    foreach (var prop in typeof(TSourceType).GetNavigationCollectionProperties(db))
                    {
                        definition.PrepareProperty(prop.Name, (destinationObject, destinationProperty, sourceObject, context) =>
                        {
                            if (context.ContainsKey(DbKey))
                            {
                                var expandDb = context[DbKey] as TContext;
                                expandDb.Attach(sourceObject as TSourceType);
                                expandDb.Entry(sourceObject as TSourceType).Collection(prop.Name).Load();
                            }
                        });
                    }
                }
            }));
        }