Landman Code Exploring my outer regions of coding.

A blog about C#, Delphi, assembler and general developer stuff.

Landman Code Exploring my outer regions of coding.

A blog about C#, Delphi, assembler and general developer stuff.

Protection your EntityCollections from outside abuse by wrapping them as IEnumerable

In the previous post I introduced a wrapping extension for Entity Framework, and used enumerations as example, but there are is one more powerful feature which this offers, you can hide your internal details from outside users.

Why would for instance some external piece of code need to have access to the EntityCollection.Remove method when the only one with access should be the entity itself or perhaps the aggregate root. Entity Framework forces you to use EntityCollections for relations were most of the times a IEnumerable would be a much better abstraction.

In our projects we have code such as the following to wrap these EntityCollections:

public partial class Order
{
	public IEnumerable<OrderDetail> Details
	{
		get
		{
			// Lazy loading in EF1
			if (!DbDetails.IsLoaded && !(this.IsDetached() || this.IsNew()))
				DbDetails.Load();
			return DbDetails;
		}
	}
}

Using this collection in any kind of query will trigger NotSupportedException from Entity Framework the same as the previous post. But when using the EFWrappableFields extension the queries are also translated to use the DbDetails when translating to SQL and thereby solves the problem and provides the possibility of hiding the real EntityCollection behind a safe IEnumerable interface.

So have fun with this extension, and when you can improve the code, please fork me at Github.

4 comments:

  1. se7en said:

    Just FYI

    switch (remainingBytes)
    {
    case 3:
    h ^= (UInt16)(*realData);
    h ^= ((UInt32)(*(((Byte*)(realData)) + 2))) << 16;
    h *= m;
    break;
    case 2:
    h ^= (UInt16)(*realData);
    h *= m;
    break;
    case 1:
    h ^= *((Byte*)realData);
    h *= m;
    break;
    default:
    break;
    }

    Should be

    switch (remainingBytes)
    {
    case 3:
    h ^= (UInt16)(*realData);
    h ^= ((UInt32)(*(((Byte*)(realData)) + 2))) << 16;
    goto case default;
    break;
    case 2:
    h ^= (UInt16)(*realData);
    goto case default;
    break;
    case 1:
    h ^= *((Byte*)realData);
    goto case default;
    default:
    h *= m;
    break;
    }

    To be slightly faster.. you figure out why

    at 04 July, 2011 09:58  
  2. Davy Landman said:

    hi se7en,

    It's always nice to explain a comment instead of "you figure out why", not just for me (reduced code size I guess?, same result could be just putting it after the switch) but for other readers as well.

    Plus, commenting it to the right post would help ;)

    Thanks for your improvement though.
    Davy

    at 04 July, 2011 10:01  
  3. 6b5a33d4-a613-11e0-b335-000bcdca4d7a said:

    My sincerest apologies...

    This is because I wanted you to realize the true nature of your own code which was really as follows:

    switch (remainingBytes)
    {
    default:
    h *= m;
    break;
    case 1:
    h ^= *((Byte*)realData);
    goto case default;
    case 2:
    case 3:
    h ^= (UInt16)(*realData);
    if(remainingBytes == 2) goto case default;
    h ^= ((UInt32)(*(((Byte*)(realData)) + 2))) << 16;
    goto case default;
    break;
    }

    Yes the stack is one reason the other is the operations in the code and I am sure that there are numerous others.

    A r3a11y g00d compiler (E.g. the compilers of generation next) would optimize this away as I have manually by fully evaluating the entire code region in use as well as be able to detect conditions of infinite loops in certain statements.

    Regards,
    v//

    at 08 July, 2011 00:31  
  4. se7en said:

    My sincerest apologies...

    This is because I wanted you to realize the true nature of your own code which was really as follows:

    switch (remainingBytes)
    {
    default:
    h *= m;
    break;
    case 1:
    h ^= *((Byte*)realData);
    goto case default;
    case 2:
    case 3:
    h ^= (UInt16)(*realData);
    if(remainingBytes == 2) goto case default;
    h ^= ((UInt32)(*(((Byte*)(realData)) + 2))) << 16;
    goto case default;
    break;
    }

    Yes the stack is one reason the other is the operations in the code and I am sure that there are numerous others.

    A r3a11y g00d compiler (E.g. the compilers of generation next) would optimize this away as I have manually by fully evaluating the entire code region in use as well as be able to detect conditions of infinite loops in certain statements.

    Regards,
    v//

    at 08 July, 2011 00:32  

Post a Comment