5
\$\begingroup\$

This code feels like it goes through too many conversions to accomplish my goal:

based on an IEnumerable of ids get those objects from a data store and set their DisplayOrder property to the position of the associated id.

Is there a more elegant solution that I'm missing?

public void ReorderElements(IEnumerable<int> elementSks)
{
 var elementsToReorder = GetSession().QueryOver<DocumentElement>()
 .WhereRestrictionOn(de => de.DocumentElementSk).IsIn(elementSks.ToArray()).List();
 var elementOrder = elementSks.Select((sk, i) => new { Sk = sk, Order = i })
 .ToDictionary(p => p.Sk, p => p.Order);
 elementsToReorder.ToList()
 .ForEach(e => e.DisplayOrder = elementOrder[e.DocumentElementSk]);
 this.Save(elementsToReorder);
}
asked Mar 7, 2012 at 19:41
\$\endgroup\$
4
  • \$\begingroup\$ Are the elementSks in any particular order when the enter the method? \$\endgroup\$ Commented Mar 7, 2012 at 19:55
  • \$\begingroup\$ @sgriffinusa The ids are posted in order from a web page and then sent to this repository method. \$\endgroup\$ Commented Mar 7, 2012 at 21:40
  • \$\begingroup\$ Sorry, I should have been more specific, what I want to know is if they are sorted. \$\endgroup\$ Commented Mar 7, 2012 at 21:43
  • \$\begingroup\$ @sgriffinusa yes the ids are in the order I want them in. The elements retrieved from the data store are ordered by their primary key. So I have to update them based on the position of the ids in elementSks. \$\endgroup\$ Commented Mar 7, 2012 at 21:46

2 Answers 2

2
\$\begingroup\$

If the list on input is going to be short, or if performance doesn't matter to you, you can simplify the code by using IndexOf() instead of the dictionary:

public void ReorderElements(IEnumerable<int> elementSks)
{
 var elementsToReorder = GetSession().QueryOver<DocumentElement>()
 .WhereRestrictionOn(de => de.DocumentElementSk).IsIn(elementSks.ToArray()).List();
 var elementOrder = elementSks.ToList();
 foreach(var element in elementsToReorder)
 element.DisplayOrder = elementOrder.IndexOf(element.DocumentElementSk);
 this.Save(elementsToReorder);
}
answered Mar 7, 2012 at 20:57
\$\endgroup\$
0
1
\$\begingroup\$

Please try this. I wrote this without testing or even compiling.

public void ReorderElements(IEnumerable<int> elementSks)
{
 var skToElementsToReorder = GetSession().QueryOver<DocumentElement>()
 .WhereRestrictionOn(de => de.DocumentElementSk).IsIn(elementSks.ToArray())
 .ToDictionary(el => el.DocumentElementSk, el => el);
 int index = 0;
 foreach(int sk in elementSks)
 {
 // Assumes that the key exists - the .IsIn restriction right before helps
 skToElementsToReorder[sk].DisplayOrder = index++;
 }
 this.Save(elementsToReorder);
}

Somehow I think that this can help: http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b (as long as you can zip elementSks together with an index. Let me try a simpler version:

public class /* or struct ? */Element 
{
 public string name;
 public in sk;
 public int index;
}
// I am not fluent in LINQ, but Linq.Zip might help to generate these?
public class SkTuple
{
 int sk;
 int index;
}
// Now you have an `IEnumerable` of each somehow, and you want to do an update at the same time as you do a join ... like this? 

https://stackoverflow.com/questions/709560/linq-in-line-property-update-during-join

This kind of got me thinking that maybe SQL is king after all - perhaps you want to just save this list of ids into a temp table where table id will be the index, and then call a stored procedure which will use a join and an update like here.

Glorfindel
1,1133 gold badges14 silver badges27 bronze badges
answered Mar 8, 2012 at 1:48
\$\endgroup\$
1
  • \$\begingroup\$ The linq to retrieve elementsToReorder is NHibernate's new QueryOver syntax. It's just a rehashing of their ICriteria expression syntax. It boils down to SQL and doesn't have that much affect on performance. Everything after the object retrieval is what I'm most worried about. \$\endgroup\$ Commented Mar 8, 2012 at 3:43

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.