EntityCollectionBase at runtime (2.0)

Posts   
 
    
Isz
User
Posts: 108
Joined: 26-Jan-2006
# Posted on: 30-Jul-2006 16:39:29   

Hi team!

Migrating to 2.0 and get the folowing compile error:

Using the generic type 'SD.LLBLGen.Pro.ORMSupportClasses.EntityCollectionBase<TEntity>' requires '1' type arguments 

I read up in the help something about EntityCollectionBase having inheritance issues, and I am guessing that is what my problem is now. I am using a generic base class I wrote that uses EntityCollectionBase. Child classes of this base class will dynamically set which EntityCollection EntityCollectionBase really is. Here is the code for my base class:


    public class QueryCollectionBase : IQueryCollection
    {
        private EntityCollectionBase collection;
        public EntityCollectionBase Collection
        {
            get{return this.collection;}
            set{this.collection = value;}
        }

        public QueryCollectionBase()
        {
            this.selectFilter = new PredicateExpression(); 
            this.maxNumberOfItemsToReturn = 0;
            this.sortClauses = new SortExpression();
            this.preFetchPath = null;
            this.relations = new RelationCollection();
        }

        /// <summary>
        /// A predicate or predicate expression which should be used as filter for the entities to retrieve.
        /// </summary>
        /// 
        private PredicateExpression selectFilter;
        public virtual PredicateExpression SelectFilter
        {
            set{this.selectFilter = value;}
            get{return selectFilter;}
        }

        /// <summary>
        /// The maximum number of items to return with this retrieval query.  0 if no limit
        /// </summary>67
        private int maxNumberOfItemsToReturn;
        public int MaxNumberOfItemsToReturn
        {
            set{maxNumberOfItemsToReturn = value;}
            get{return maxNumberOfItemsToReturn;}
        }

        /// <summary>
        /// The order by specifications for the sorting of the resultset. When not specified, no sorting is applied.
        /// </summary>
        private SortExpression sortClauses;
        public virtual SortExpression SortClauses
        {
            set{this.sortClauses = value;}
            get{return sortClauses;}
        }

        /// <summary>
        /// The prefetch path to use.  This is null by default and must be instantiated to the EntityType that is being used
        /// </summary>
        private IPrefetchPath preFetchPath;
        public virtual IPrefetchPath PreFetchPath
        {
            set{this.preFetchPath = value;}
            get{return preFetchPath;}
        }

        /// <summary>
        /// The set of relations to walk to construct the total query.
        /// </summary>
        private RelationCollection relations;
        public virtual RelationCollection Relations
        {
            set{this.relations = value;}
            get{return relations;}
        }

        /// <summary>
        /// The page number to retrieve. 0 if pagination is not in use.
        /// </summary>
        private int pageNumber;
        public virtual int PageNumber
        {
            set{pageNumber = value;}
            get{return pageNumber;}
        }

        /// <summary>
        /// The page size of the page to retrieve. 0 if pagination is not in use.
        /// </summary>
        private int pageSize;
        public virtual int PageSize
        {
            set{pageSize = value;}
            get{return pageSize;}
        }

        /// <summary>
        /// The the current index of the page to calculate each line.
        /// </summary>
        public virtual int PageIndex
        {
            get{return (this.pageNumber * this.pageSize) - this.pageSize;}
        }

        /// <summary>
        /// The count as provided by GetDbCount(), and is not the same as Collection.Count.  This is readonly.
        /// </summary>
        private int count;
        public virtual int Count
        {
            get{return count;}
        }

        public virtual void FillCollection ()
        {           
            this.Collection.GetMulti(this.SelectFilter, this.MaxNumberOfItemsToReturn, this.SortClauses, this.Relations, this.PreFetchPath, this.PageNumber, this.PageSize);
            this.count = this.Collection.GetDbCount(this.SelectFilter, this.Relations);
        }
    }


Then I might write a child class like the following which uses the EnitytCollectionBase to perform a GetMulti:


    public class ArticleQueryCollection : QueryCollectionBase
    {
        ArticleCollection ArticleCollection;

        private ArticleQueries articleQuery = ArticleQueries.Undefined;
        public ArticleQueries ArticleQuery
        {
            get{return this.articleQuery;}
            set{this.articleQuery = value;}
        }

        private int topicId = DataProperties.UNDEFINED_INTEGER;
        public int TopicId
        {
            set{this.topicId = value;}
        }

        private int articleId = DataProperties.UNDEFINED_INTEGER;
        public int ArticleId
        {
            set{this.articleId = value;}
        }

        private int month = DataProperties.UNDEFINED_INTEGER;
        public int Month
        {
            get{return this.month;}
            set{this.month = value;}
        }

        private int year = DataProperties.UNDEFINED_INTEGER;
        public int Year
        {
            get{return this.year;}
            set{this.year = value;}
        }

        public ArticleQueryCollection()
        {
            this.ArticleCollection = new ArticleCollection();
            _ArticleQueryCollection();
        }

        private void _ArticleQueryCollection()
        {
            base.Collection = this.ArticleCollection;
        }
        
        public override void FillCollection()
        {
            QueryFactory();
            base.FillCollection();
        }

        #region Custom Predicates

        /// <summary>
        /// This factory calls the specific query to be used.
        /// </summary>
        private void QueryFactory()
        {
            switch(this.ArticleQuery)
            {
                case ArticleQueries.RecentArticlesFromAllTopics :
                    QueryRecentArticlesFromAllTopics();
                    break;

                case ArticleQueries.ArchiveArticlesBySelectedMonthYear :
                    QueryArchiveArticlesBySelectedMonthYear();
                    break;
            }
        }

        /// <summary>
        /// </summary>
        private void QueryRecentArticlesFromAllTopics()
        {   
            PrefetchPath preFetchArticleEntity = new PrefetchPath((int)EntityType.ArticleEntity);
            IPrefetchPathElement prefetchTopic = ArticleEntity.PrefetchPathTopic;
            preFetchArticleEntity.Add(prefetchTopic);
            
            SortExpression sorter = new SortExpression();
            sorter.Add(SortClauseFactory.Create(ArticleFieldIndex.CreateDate, SortOperator.Descending));

            base.PreFetchPath = preFetchArticleEntity;
            base.MaxNumberOfItemsToReturn = 20;
            base.SortClauses = sorter;
        }

        
        private void QueryArchiveArticlesBySelectedMonthYear()
        {
            IExpression monthCall = new DbFunctionCall( "MONTH", new object[]{ArticleFields.CreateDate});
            IExpression yearCall = new DbFunctionCall( "YEAR", new object[]{ArticleFields.CreateDate});

            PredicateExpression selectFilter = new PredicateExpression();
            selectFilter.Add(new FieldCompareValuePredicate(ArticleFields.ArticleTopicId, ComparisonOperator.Equal, this.topicId));
            FieldCompareValuePredicate filterMonth = PredicateFactory.CompareValue(ArticleFieldIndex.CreateDate, ComparisonOperator.Equal, this.Month);
            FieldCompareValuePredicate filterYear = PredicateFactory.CompareValue(ArticleFieldIndex.CreateDate, ComparisonOperator.Equal, this.Year);
            filterMonth.FieldCore.ExpressionToApply = monthCall;
            filterYear.FieldCore.ExpressionToApply = yearCall;
            selectFilter.AddWithAnd(filterMonth);
            selectFilter.AddWithAnd(filterYear);

            base.SelectFilter = selectFilter;
        }

        #endregion

    }

    public enum ArticleQueries : int
    {
        Undefined = 0,
        RecentArticlesFromAllTopics = 1,
        ArchiveArticlesBySelectedMonthYear = 2,
    }


If I understand correctly the new EnitytCollectionBase requires a type as in:

EnitytCollectionBase<ArticleEntity>

Is there anyway to set this at runtime, such that the type is dynamically set? If this isn't possible, can someone suggest a better alternative?

Thanks!

Isz
User
Posts: 108
Joined: 26-Jan-2006
# Posted on: 30-Jul-2006 17:42:34   

I think I may have figured it out... needed to read up a little bit on Generics. sunglasses

Isz
User
Posts: 108
Joined: 26-Jan-2006
# Posted on: 31-Jul-2006 00:06:10   

Might have jumped the gun...

Using the code laid out above I modified it to use generics, but now I am not sure how I would call this.collection.GetMulti(params) since this.collection is null, and I can't seem to set it to a new instance of ArticleCollection through the child class.

Here is the abbreviated base class:



    public class QueryCollectionBase<TEntity> : IQueryCollection<TEntity>
    {
        private EntityCollectionBase<EntityBase> collection;
        public EntityCollectionBase<EntityBase> Collection
        {
            get{return this.collection;}
            set{this.collection = value;}
        }

        ...

        public virtual void FillCollection ()
        {           
            this.Collection.GetMulti(this.SelectFilter, this.MaxNumberOfItemsToReturn, this.SortClauses, this.Relations, this.PreFetchPath, this.PageNumber, this.PageSize);
            this.count = this.Collection.GetDbCount(this.SelectFilter, this.Relations);
        }
        ...



Then here is my abbreviated child class, which defines what type the base class' EntityCollectionBase should be, which I think is great, but then what would I set base.Collection to as currently this.ArticleCollection is not compilable?



    public class ArticleQueryCollection : QueryCollectionBase<ArticleEntity>
    {
        ArticleCollection ArticleCollection;

        ...
    
        public ArticleQueryCollection()
        {
            this.ArticleCollection = new ArticleCollection();
            _ArticleQueryCollection();
        }

        private void _ArticleQueryCollection()
        {
                       base.Collection = this.ArticleCollection;
        }
        ...
        


confused

Thanks!

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 31-Jul-2006 07:33:58   

I guess you code should look like the following:

Base class:

public class QueryCollectionBase<IEntity> : IQueryCollection<IEntity>
    {
        private EntityCollectionBase<IEntity> collection;
        public EntityCollectionBase<IEntity> Collection
        {
            get{return this.collection;}
            set{this.collection = value;}
        }

Child class:

public class ArticleQueryCollection : QueryCollectionBase<ArticleEntity>
    {
        EntityCollectionBase<ArticleEntity>  ArticleCollection;

        ...
    
        public ArticleQueryCollection()
        {
            this.ArticleCollection = new EntityCollectionBase<ArticleEntity>();
            _ArticleQueryCollection();
        }

        private void _ArticleQueryCollection()
        {
                     base.Collection = this.ArticleCollection;
        }
        ...

Isz
User
Posts: 108
Joined: 26-Jan-2006
# Posted on: 31-Jul-2006 12:25:01   

Thanks for the response Walaa..

I tried to change to the code above, but here are the compile errors I get:

Base Class:


    public class ArticleQueryCollection : QueryCollectionBase<ArticleEntity>
    {
                EntityCollectionBase<ArticleEntity> ArticleCollection;

        public ArticleQueryCollection()
        {
            this.ArticleCollection = new EntityCollectionBase<ArticleEntity>();
            _ArticleQueryCollection();
        }

        private void _ArticleQueryCollection()
        {
            base.Collection = this.ArticleCollection;
        }


Chid Class:


    public class QueryCollectionBase<IEntity> : IQueryCollection<IEntity>
    {
        private EntityCollectionBase<IEntity> collection;
        public EntityCollectionBase<IEntity> Collection
        {
            get
            {
                return this.collection;
            }
            set{this.collection = value;}
        }



Compile Error:


The type 'IEntity' must be convertible to 'SD.LLBLGen.Pro.ORMSupportClasses.EntityBase' in order to use it as parameter 'TEntity' in the generic type or method 'SD.LLBLGen.Pro.ORMSupportClasses.EntityCollectionBase<TEntity>'    

If I change it to the following, then I get another error:


    public class QueryCollectionBase<TEntity> : IQueryCollection<TEntity>
    {
        private EntityCollectionBase<EntityBase> collection;
        public EntityCollectionBase<EntityBase> Collection
        {
            get
            {
                return this.collection;
            }
            set{this.collection = value;}
        }




Cannot create an instance of the abstract class or interface 'SD.LLBLGen.Pro.ORMSupportClasses.EntityCollectionBase<LightMission.DataEntities.EntityClasses.ArticleEntity>'

Which referes to the Child class:


...

        public ArticleQueryCollection()
        {
            this.ArticleCollection = new EntityCollectionBase<ArticleEntity>();
            _ArticleQueryCollection();
        }

...

The above error makes sense since EntityCoolectionBase is marked as abstract. Any more ideas?

Thanks!

Isz
User
Posts: 108
Joined: 26-Jan-2006
# Posted on: 01-Aug-2006 03:36:58   

Ya know... I just changed everything to use IEntityCollection instead of EntityCollectionBase. I am not sure why I originally used EntityCollectionBase, perhaps there was a reason. But hopefully it all works now.

Thanks for the help!