Dynamically nesting queries

Posts   
 
    
Maciek
User
Posts: 23
Joined: 28-Aug-2008
# Posted on: 08-Sep-2008 10:09:47   

Hi,

I'd like to dynamically nest linq queries like in the following example:


var timeFilter = (from c in metaData.Document
                  join mid in metaData.MetadataInDocument on c.ID equals mid.DocumentID
                  join m in metaData.Metadata on mid.MetadataID equals m.ID
                  where m.Name == "Date" && m.Date < DateTime.Now.AddHours(-10.0)
                  select c.ID).Distinct();

var nameAndTimeFilter = (from c2 in metaData.Document
                   join mid2 in metaData.MetadataInDocument on c2.ID equals mid2.DocumentID
                   join m2 in metaData.Metadata on mid2.MetadataID equals m2.ID
                   where m2.Name == "Name" && m2.Name == "New Document" && timeFilter.Contains(c2.ID)
                   select c2.ID).Distinct();

var otherAndNameAndTimeFilter = (from c3 in metaData.Document
                   join mid3 in metaData.MetadataInDocument on c3.ID equals mid3.DocumentID
                   join m3 in metaData.Metadata on mid3.MetadataID equals m3.ID
                   where m3.Name == "Other" && m3.Boolean == false && nameAndTimeFilter.Contains(c3.ID)
                   select c3.ID);

In order to make code above work i had to change variable names (c,c2,c3 .. mid,mid2,mid3) and that makes it impossible to dynamically nest them.

What's the best aproach to dynamically filter entities based on what collection of entities they are associated with?

Walaa avatar
Walaa
Support Team
Posts: 14993
Joined: 21-Aug-2005
# Posted on: 08-Sep-2008 11:37:23   

What's the best aproach to dynamically filter entities based on what collection of entities they are associated with?

Would you please elaborate more? Also in this context, what do you mean by dynamically?

Maciek
User
Posts: 23
Joined: 28-Aug-2008
# Posted on: 08-Sep-2008 11:48:52   

Walaa wrote:

Also in this context, what do you mean by dynamically?


        public IEnumerable<long> TimeFilter()
        {
            LinqMetaData metaData = new LinqMetaData();

            return (from c in metaData.Document
                    join mid in metaData.MetadataInDocument on c.ID equals mid.DocumentID
                    join m in metaData.Metadata on mid.MetadataID equals m.ID
                    where m.Name == "Date" && m.Date < DateTime.Now.AddHours(-10.0)
                    select c.ID).Distinct();
        }

        // ....

        public IEnumerable<long> OtherFilter(IEnumerable<long> filter)
        {
            LinqMetaData metaData = new LinqMetaData();
            
            return (from c in metaData.Document
                    join mid in metaData.MetadataInDocument on c.ID equals mid.DocumentID
                    join m in metaData.Metadata on mid.MetadataID equals m.ID
                    where m.Name == "Other" && m.Boolean == false && filter.Contains(c.ID)
                    select c.ID).Distinct();
        }

public main()
{
            // Filters are chosen in the runtime by the user and then nested like this:
            var f1 = TimeFilter();
            var f2 = OtherFilter(f1);
            ....
            var fn = WheteverFilter(fn-1); // 'fn-1' is a variable name

            foreach (var item in fn) // Error*
            {
                var temp = item; // Only documents that satisfy f1 and f2 and ... and fn
            }
}

  • Relation at index 1 doesn't contain an entity already added to the FROM clause. Bad alias?

Walaa wrote:

Would you please elaborate more?

I've got a Document table and a Metadata table connected via MetadataInDocument table.

I'd like to get only documents that have connected to them for exaple this metadatas: metadata{ Name = "Date", Date = DateTime.Now} and metadata{ Name = "Other", Boolean = false}.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39865
Joined: 17-Aug-2003
# Posted on: 08-Sep-2008 13:51:37   

The error suggests you're using an older build of the linq provider/ormsupportclasses, please use the latest build available in the customer area.

Also, please have a look at the predicatebuilder class in this thread: http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=14224

which I think gives you another way to do this.

Also, I think this is a different, better way to do this:


public IQueryble<DocumentEntity> GetDocuments(LinqMetaData metaData)
{
    return from d in metaData.Documents select d;
}

public IQueryable<DocumentEntity> FilterOne(IQueryable<DocumentEntity> toFilter)
{
    return toFilter.Any(d=>d.MetaDataInDocument.MetaData.Any(m=>m.Name=="Date" && m.Date< DateTime.Now.AddHours(-10.0)));
}

etc.

public Main()
{
    LinqMetaData metaData = new LinqMetaData();
    var q = GetDocuments(metaData);
    q = FilterOne(q);
    //...
    
    var q = (from d in q
            select d.ID).Distinct();
            
    //...
}


This too requires a recent build as nested Any clauses could cause problems in edge cases, so a recent build which fixes this bug is required. Please let us know if this works or not and if not (i.e crashes with exceptions) please post the FULL stacktrace and the query produced (through DQE tracing, see 'troubleshooting and debugging' in manual).

Frans Bouma | Lead developer LLBLGen Pro