Matt Connolly
Matt Connolly

Reputation: 1233

Linq to SQL ordered child collection

Is there a way to define a default order column from a child collection? In my case, I have a Form entity that has a collection of FormItem entities called FormItems. FormItem has a property called DisplayOrder (int). I want to make sure that any Form entities I return from a method have that collection properly ordered. Is there a way to do this before returning the result?

For example, I tried this but the list is not actually sorted:

var form = context.Forms.FirstOrDefault(x => x.IsDeleted == false && x.FormName == formName);
if (form != null)
{
    form.FormItems.OrderBy(x => x.DisplayOrder);
    // I can't even figure out a way to cast this next line so that it will compile
    // form.FormItems = form.FormItems.OrderBy(x => x.DisplayOrder);
}
return form;

Is there a way to do this without using DataLoadOptions?

Upvotes: 3

Views: 580

Answers (5)

maxlego
maxlego

Reputation: 4914

One option would be

public static class FormExtensions
{
        public static IQueryable<FormItem> GetOrderedItems(this Form form)
        {
                // without lazy loading, but you have to get current context somehow
                return CurrentContext.FormItems.Where(x => x.FormId == form.Id).OrderBy(x => x.DisplayOrder);

               // with lazy loading
               return form.FormItems.OrderBy(x => x.DisplayOrder);
        }
}

or create reprository layer for stuff like that

Upvotes: 0

Oleks
Oleks

Reputation: 32343

Try this:

DataLoadOptions loadOptions = new DataLoadOptions();
loadOptions.LoadWith<Form>(f => f.FormItems);
loadOptions.AssociateWith<Form>(f => 
    f.FormItems
        .OrderBy(fi => fi.DisplayOrder);
);

context.LoadOptions = context;

var form = context.Forms
    .FirstOrDefault(x => 
        !x.IsDeleted &&
        x.FormName == formName
    );

meaning, ordering of child items made by DataLoadOptions.AssociateWith method.

Upvotes: 1

Robert Ivanc
Robert Ivanc

Reputation: 1440

what about:

var form2 = form.FormItems.OrderBy(x => x.DisplayOrder); return form2;

Upvotes: 0

st78
st78

Reputation: 8316

First, Make FormItems private and change name to PrivateFormNames in designer.

Than you should be able to declare:

partial class Form
{
    public IQueryable<FormItem> FormItems
    { 
        get { return PrivateFormItems.OrderBy(x => x.DisplayOrder); } 
    }
}

I will think how you can make it virtual... Something like this: You can create Derived class for Form in linq digram, and set inheritance in that way, that it always create derived Form class (You can specify inheritence default).

Than you can mark FormItems as virtual and override it in derived class:

 partial class FormDerived
    {
        public override IQueryable<FormItem> FormItems
        { 
            get { return base.FormItems.OrderBy(x => x.DisplayOrder); } 
        }
    }

and ALL linq and application will start to use ordered list. Only option to get it unordered will be to use context.FormItems.

Upvotes: 0

bruno conde
bruno conde

Reputation: 48255

You could add an additional property to your Form entity trough a partial class that would return the ordered FormItems.

partial class Form
{
    public IQueryable<FormItem> OrderedFormItems
    { 
        get { return FormItems.OrderBy(x => x.DisplayOrder); } 
    }
}

Upvotes: 0

Related Questions