MyEntity.ToList() => EntityCollection

Posts   
 
    
ianvink
User
Posts: 393
Joined: 15-Dec-2006
# Posted on: 20-Jun-2008 15:07:04   

LINQ Newbie Question.

When I get a result set back I wish to return the data to my LLBLGenProDataSource2.

This is how I do it. Is there a better way?


        public static EntityCollection<PersonEntity> GetPeopleWithNamesBeginningWith(string NameBeginsWith)
        {
            //Get the data from the DB using LINQ
            LinqMetaData metaLinq = new LinqMetaData(SampleAdapter.GetAdapter());

            var people = from name in metaLinq.Person
                         where name.Name.StartsWith(NameBeginsWith)
                         select name;

            //Put the results into an EntityCollection
            EntityCollection<PersonEntity> retVal = new EntityCollection<PersonEntity>();
            foreach (PersonEntity personEntity in people)
            {
                retVal.Add(personEntity);
            }

            return retVal;
        }

Walaa avatar
Walaa
Support Team
Posts: 14946
Joined: 21-Aug-2005
# Posted on: 20-Jun-2008 15:17:13   

As far as I understand the question, I think you need to use the before mentioned code inside the PerformSelect event of the LLBLGenProDataSource and set the datasource's entity collection to the fetched collection.

Hint: Set the datasource's LivePersistence property to false.

ianvink
User
Posts: 393
Joined: 15-Dec-2006
# Posted on: 20-Jun-2008 15:43:33   

Sorry for the confusion. I was referring to if this is the correct way to get an EntityCollection<> out of a LINQ query.


            //Put the results into an EntityCollection
            EntityCollection<PersonEntity> retVal = new EntityCollection<PersonEntity>();
            foreach (PersonEntity personEntity in people)
            {
                retVal.Add(personEntity);
            }

It works fine, just thought there may be an easier way.

swallace
User
Posts: 648
Joined: 18-Aug-2003
# Posted on: 20-Jun-2008 15:46:44   

What you're really looking for this the .Execute function. Here's some example code from a question I had in a previous thread:

SortExpression mOrderBySections = new SortExpression(ArticleSectionFields.Sectionorder | SortOperator.Ascending);
SortExpression mOrderByLanguages = new SortExpression(LanguageFields.Name | SortOperator.Ascending);
SortExpression mOrderByTechnology = new SortExpression(TechnologyFields.Name | SortOperator.Ascending);

LinqMetaData metaData = new LinqMetaData(mAdapter);

var q = (from a in metaData.Article
         select a)
        .WithPath(
            new PathEdge<ArticleSectionEntity>(ArticleEntity.PrefetchPathArticleSections, null, mOrderBySections, 0),
            new PathEdge<LanguageEntity>(ArticleEntity.PrefetchPathLanguages, null, mOrderByLanguages, 0),
            new PathEdge<TechnologyEntity>(ArticleEntity.PrefetchPathTechnologies, null, mOrderByTechnology, 0),
            new PathEdge<UserEntity>(ArticleEntity.PrefetchPathWrittenByUser));

EntityCollection<ArticleEntity> mArticles = ((ILLBLGenProQuery)q).Execute<EntityCollection<ArticleEntity>>();

Note the cast to ILLBLGenProQuery. This will eliminate the foreach iteration you're doing now.

Love that Linq!

ianvink
User
Posts: 393
Joined: 15-Dec-2006
# Posted on: 20-Jun-2008 15:50:20   

Perfect!

I have changed the code to this and it works great. This is getting toooooooo easy......


        public static EntityCollection<PersonEntity> GetPeopleWithNamesBeginningWith(string NameBeginsWith)
        {
            //Get the data from the DB using LINQ
            LinqMetaData metaLinq = new LinqMetaData(SampleAdapter.GetAdapter());
            var peoples = from e in metaLinq.Person
                         where e.Name.StartsWith(NameBeginsWith)
                         select e;
            EntityCollection<PersonEntity> retVal = ((ILLBLGenProQuery)peoples).Execute<EntityCollection<PersonEntity>>();
            return retVal;
        }

swallace
User
Posts: 648
Joined: 18-Aug-2003
# Posted on: 20-Jun-2008 15:54:20   

If you've not spent time reviewing the unittests provided, you'll want to do that. I learned a great deal from browsing that code, especially the simple things. It's located:

Program Files\Solutions Design\LLBLGen Pro v2.6\Sourcecode\LinqUnitTests

Well worth the hour or so I spent.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 20-Jun-2008 16:45:01   

swallace wrote:

What you're really looking for this the .Execute function. Here's some example code from a question I had in a previous thread:

SortExpression mOrderBySections = new SortExpression(ArticleSectionFields.Sectionorder | SortOperator.Ascending);
SortExpression mOrderByLanguages = new SortExpression(LanguageFields.Name | SortOperator.Ascending);
SortExpression mOrderByTechnology = new SortExpression(TechnologyFields.Name | SortOperator.Ascending);

LinqMetaData metaData = new LinqMetaData(mAdapter);

var q = (from a in metaData.Article
         select a)
        .WithPath(
            new PathEdge<ArticleSectionEntity>(ArticleEntity.PrefetchPathArticleSections, null, mOrderBySections, 0),
            new PathEdge<LanguageEntity>(ArticleEntity.PrefetchPathLanguages, null, mOrderByLanguages, 0),
            new PathEdge<TechnologyEntity>(ArticleEntity.PrefetchPathTechnologies, null, mOrderByTechnology, 0),
            new PathEdge<UserEntity>(ArticleEntity.PrefetchPathWrittenByUser));

EntityCollection<ArticleEntity> mArticles = ((ILLBLGenProQuery)q).Execute<EntityCollection<ArticleEntity>>();

Note the cast to ILLBLGenProQuery. This will eliminate the foreach iteration you're doing now.

Love that Linq!

smile

Btw, you can linq-ify it even further with the WithPath<T>(path... ) linq statements. Though it requires more insight in how lambda's work, so the code might not be more readable than the code above, however you can formulate it completely inside the Withpath statement, without llblgen pro constructs like .PrefetchPath... and a sortclause.

Frans Bouma | Lead developer LLBLGen Pro
swallace
User
Posts: 648
Joined: 18-Aug-2003
# Posted on: 20-Jun-2008 17:42:15   

Lamdas are where I'm weak right now. I'm two weeks into my Linq education, and working my way up.

Thanks for making the sample code/unit tests. Great stuff!

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 20-Jun-2008 17:56:05   

swallace wrote:

Lamdas are where I'm weak right now. I'm two weeks into my Linq education, and working my way up.

Thanks for making the sample code/unit tests. Great stuff!

simple_smile Yes, the lambda's are hard to write at times, and could lead to more complex code at first glance. If I have to take a guess, I think this is how you could do your query with WithPath and the lambda variant:

var q = (from a in metaData.Article
         select a)
        .WithPath(articlePath => articlePath
            .Prefetch<ArticleSectionEntity>(a=>a.ArticleSections).OrderBy(as=>as.Sectionorder)
            .Prefetch<LanguageEntity>(a=>a.Languages).OrderBy(l=>l.Name)
            .Prefetch<TechnologyEntity>(a=>a.Technologies).OrderBy(t=>t.Name)
            .Prefetch<UserEntity>(a=>a.WrittenByUser);

so without the SortExpressions, which are now embedded inside the query simple_smile

Frans Bouma | Lead developer LLBLGen Pro
swallace
User
Posts: 648
Joined: 18-Aug-2003
# Posted on: 21-Jun-2008 03:04:55   

I'll give that a whirl, thanks!

GabeNodland avatar
Posts: 65
Joined: 31-Dec-2004
# Posted on: 16-Sep-2008 19:59:18   

This is something that seems like we need to do often, and the execute code is a bit cumbersome so, what about something like this?



Public Module LLBLGenProQueryExtender
    <System.Runtime.CompilerServices.Extension()> _
    Public Function ToEntityCollection(Of t As EntityBase2)(ByVal q As IQueryable) As EntityCollection(Of t)
        If Not TypeOf q Is ILLBLGenProQuery Then
            Throw New ApplicationException("Only ILLBLGenProQuery may be outputed as EntityCollections")
        End If

        Return CType(q, ILLBLGenProQuery).Execute(Of EntityCollection(Of t))()
    End Function

End Module


so you can do this:

Dim meta = New metadata(New dataadapter)
            Dim q = From d In meta.Document Where _
                    d.PartId.Equals(part.PartId) OrElse _
                    (d.CompanyId.Equals(part.CompanyId) AndAlso d.PartId.HasValue) _
                    Select d

            If prefetchDocumentGroups Then
                q = q.WithPath(New PathEdge(Of DocumentGroupEntity)(DocumentEntity.PrefetchPathDocumentType))
            End If

            If prefetchDocumentTypes Then
                q = q.WithPath(New PathEdge(Of DocumentTypeEntity)(DocumentEntity.PrefetchPathDocumentGroups))
            End If

            Return q.ToEntityCollection(Of PartEntity)()

I made it an extension of Iqueryable because i didn't want to cast each time i use it.

Also if you put this within a namespace that you import only when you are using llbl queries, then it will not appear on Iqueryables other places.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 17-Sep-2008 16:26:38   

Good suggestion simple_smile

Frans Bouma | Lead developer LLBLGen Pro