Archive for October, 2011

SelectMany Example: Flatten Parent Child Association Into A Single List

October 28, 2011

I’m starting to get the hang of LINQ SelectMany now.

Here’s a great article which explains SelectMany better than any other I’ve read. For this James Etheredge is awarded the BTWT Golden Tadpole With Anachronistic Zeppelin for services to Brain Improvement.

So the key is to recognise that SelectMany needs a List to work on. Well, not a List exactly. SelectMany actually works on an IEnumerable. But to get started with SelectMany we can take the conceptual shortcut of thinking of SelectMany as working on instances of List.

So if I have a list of Tadpoles each of which contains a list of Zeppelins and I want to flatten that list I just say:

List (Of TadpoleZeppelins) tadZeps = tadpoles.SelectMany(tad =>
CreateTadpoleZeppelin(
tad.Zeppelins.ToList())).ToList();

CreateTadpoleZeppelin creates a list of TadpoleZeppelins out of a List of Zeppelins, like so:

CreateTadpoleZeppelin(List(Of Zeppelin) zeps)
{
List(Of TadpoleZeppelin) tadZeps = new List (Of TadpoleZeppelen)
zeps.ForEach(zep =>
{
TadpoleZeppelin tadZep = new TadpoleZeppelin();
tadZep.NumFins = zep.Tadpole.NumFins;
tadZep.HeliumCapacity = zep.HeliumCapacity;

tadZeps.Add(tadZep);
});

return tadZeps;
}

I think that’s pretty self-explanatory.

Footnote
If the example seems a bit weird just substitute ‘Customer’ for ‘Tadpole’ and ‘Order’ for ‘Zeppelin’

Advertisements

XamComboBox ComboBoxItemsProvider Very Slow In XamDataGrid

October 25, 2011

I had a page which took 10 seconds to load. When I removed the XamDataGrid Column containing my ComboBoxProvider it took less than 2 seconds to load.

The fix to make it faster was to initialize the ComboBoxProvider through a much faster class. Because ComboBoxProvider is being created once per row, the savings were massive. I also threw away some redundant Binding which cut down on processing time for every DataGridRow.

So I changed this:

igEdit:ComboBoxItemsProvider x:Key="SlowOperationTypeProvider"
ItemsSource="{Binding Source={x:Static enum:EnumDictionary.OperationTypeDictionary}}"
DisplayMemberPath="Key" ValuePath="Value"

To This

igEdit:ComboBoxItemsProvider x:Key="FastOperationTypeProvider"
ItemsSource="{Binding Source={x:Static classlib:Defaults.OperationTypes}}"

EnumDictionary uses Reflection to read a .NET DescriptionAttribute which contains a user-friendly Description for my OperationType Enum. SlowComboBoxItemsProvider iterated through the Enum, used Reflection and Object Casting to create its Dictionary, then used Reflection again to perform DataBinding.

FastComboBoxItemsProvider extracted only the Keys (strings) from an already created EnumDictionary and did not require DisplaymMemberPath or ValueMemberPath attributes. Like I say, I saved 8 seconds in a DataGrid containing only 10 rows.

Entity Framework Type FixupCollection`1 is not marked as serializable.

October 21, 2011

Entity Framework Autogenerated Classes Not Marked as Serializable.

This error comes about while trying to Serialize an EntityFramework Entity that has Associations. I got my error after creating a New entity, saving it, then doing Update on the newly created entity.

A workaround is to add the [Serializable] attribute to the FixUpCollection class, which is located in your .cs file. So, if your EF Template is called StudentEnrolment.tt then FixupCollection is located in StudentEnrolment.cs. Make FixupCollection look like this:

[Serializable]
public class FixupCollection : ObservableCollection

The permanent fix is to modify your Entity Framework template file to make sure that every time your template is run and your Entity classes regenerated then the Serializable attribute is plonked on top of the EF FixupCollection class.

So edit your equivalent StudentEnrolments.tt and find the line where FixupCollection is generated and simply insert the text “[Serializable]” above it, exactly as you would in your class definition, like so:


#>
// An System.Collections.ObjectModel.ObservableCollection that raises
// individual item removal notifications on clear and prevents adding duplicates.
[Serializable]
public class FixupCollection : ObservableCollection
{

All credit to marc_s at Stack Overflow who wrote this and Ross Pace who linked to it from here.

Once again for lovers of Stack Dumps, here’s the full error:

Type 'SubstationLoad.Data.Model.FixupCollection`1[[SubstationLoad.Data.Model.Substation, SubstationLoad.Data, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' in Assembly 'SubstationLoad.Data, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.

Adding An Additional Item To A Collection In Entity Framework With Repository Pattern

October 13, 2011

My application has Entities named ‘Hazards’ and ‘Hazard Groups’. A HazardGroup contains many Hazards and the Hazards may be moved from one HazardGroup to another via a Dialog Box.

I found when trying to add an existing Hazard to an existing HazardGroup that I was getting (to paraphrase) ‘Cannot create association: Objects were created in different Data Contexts’ error message. So I needed to put the Hazard and the HazardGroup in the same Object Context.

Here’s how I ended up doing it:

using (var ctx = new HazardContext())
{ {
Hazard movedHazard = _moved hazard returned from my Dialog Box_;
ctx.HazardGroups.Attach(SelectedHazardGroup);
ctx.Hazards.Attach(movedHazard);
SelectedHazardGroup.Hazards.Add(movedHazard);
}

Just to make it spicier I was also using the Repository Pattern, so I had to make sure that my SelectedHazardGroup was attached to the active Repository, like so:

using (var ctx = new HazardContext())
{
IRepository (Of HazardGroup) repo =
new Repository (Of HazardGroup)(ctx);

repo.Attach(SelectedHazardGroup);
Hazard movedHazard = _moved hazard returned from my Dialog Box_;
ctx.Substations.Attach(movedHazard);
SelectedHazardGroup.Hazards.Add(movedHazard);
repo.SaveChanges()
}

HTH.