views:

96

answers:

4

I keep hearing about EF 4.0, POCO, IObjectSet, UnitOfWork (by the way, UoW is atleast more than 17 years old when I first heard it) etc.

So some folks talk about Repository "pattern". etc. There are numerous bloggers showcasing their concoction of a "wrapper" or repository or something similar. But they all require IObjectSets (or in some cases - IQueryables) to be hanging off their POCOs. Expectation seems to be that you can write queries against them.

So if one needs IObjectSet and not just IList or some other simpler collection, why are we saying this is POCO and free from EF?

If I want to swap EF from underneath, I need to make sure my "other" O/R Mapper (I know I know.. EF is not just an O/R Mapper) understands IObjectSet and be able to parse the ExpressionTrees from the queries, execute and otherwise behave similar to EF.

+1  A: 

Take a look at Entity Framework Code First: http://weblogs.asp.net/scottgu/archive/2010/08/03/using-ef-code-first-with-an-existing-database.aspx

Hightechrider
Nice link Hightechrider. Thanks. Will read this one carefully - looks a better way than most what I saw on the web. At first glance, two things struck out - 1) DBSets in the "Context" and 2) EF is starting to look like ObjectSpaces. Luca Bolognese is probably chuckling somewhere right now.
+1  A: 

In response to the phrase: "If I want to swap EF from underneath":

In my business, it is more likely that I would swap out the database, say from Oracle to SQL Server (or vice versa), than that I would swap out the data access framework. On the other hand, there do exist options that make EF a favorable choice.

There are other LINQ providers than those provided by EF (e.g. LLBLGen). Sure, swapping out an EF data tier for NHibernate or EasyObjects would be difficult, because the frameworks do not have sufficient feature parity to ease the transition; however, LINQ was designed to open the way for other LINQ providers to step in and provide their own solution.

kbrimington
Good point about LINQ being open. My main concern is that anything 'swap-capable' with EF has to have a good implementation of LINQ. Having tried implementing a LINQ provider, I am not too confident that it is something that resonates with 'Plain' in POCO. As a side effect, a simpler 'overall' replacement is not possible. For example, I have a requirement to have the same application run on MSSQL and a data platform that is proprietary and non-standard. I have a basic version of IQueryable - but it is no replacement of a full fledged LINQ provider which any 'swapping' customer would expect.
@overflowstack: I can see how it would be difficult to find a good, swappable, industry-proven solution for a private, proprietary data platform. Best of luck to you.
kbrimington
+2  A: 

IObjectSet is not the interface that makes an Entity POCO, it's just the persistence container IObjectSet. The point of POCO is to prevent you from having to derive your Model classes from an EF type, which the T4 POCO template in EF4 provides.

The Repository pattern is an optional additional layer of abstraction from your ORM to allow easier implementation of a different one if the need arose. Separation of concerns etc etc.

Daz Lewis
-1: The point of POCOs is to not have any dependencies to other platforms/frameworks in your model. Needing to implement an interface that doesn't represent the interests of the Model violates that.
SnOrfus
Please go read up on EF POCO SnOrfus. You don't need to implement any interface or base type when using POCO. As I said, IObjectSet is implemented on the persistence container NOT within the Model.
Daz Lewis
"Please go read up on EF POCO SnOrfus" - Indeed. My apologies. -1 Reversed.
SnOrfus
A: 

Your question contains a wrong statement: Correct is that POCOs do not depend on IObjectSet.

POCOs themselves are independent from EF. Or better: They are supposed to be independent from EF. Since YOU are implementing the POCO classes you are finally responsible to make this sure. (Otherwise the term POCO would be the wrong one.)

If you are using the standard T4 template to create POCO classes from a model description instead of writing the classes on your own the template ensures that the classes do not depend on EF - they are not derived from Entity and collections as members of a class are generated with ICollection by this template, not with IObjectSet.

Repository pattern is another question. The POCO T4 template does not create a Repository as an abstract interface to act on a database with POCOs. It creates a derived ObjectContext which is rather an EF specific implementation of a possible repository interface (or at least helps to easily implement a possible repository interface).

If you want to have a repository interface which doesn't depend on EF or LINQ you have to define it this way. Nothing forces you to use IObjectSet or IQueryable in that interface. Perhaps the examples of implementing the Repository pattern you saw didn't intend to be independent from Entity Framework or LINQ.

An example:

Suppose, in your business layer you need a list of all products of a given category returned from the persistance layer. What would this layer expose to fulfill the request?

If you only have databases in mind which offer a LINQ provider you might design the repository interface like so:

public interface IProductsRepository
{
    IQueryable<Product> AllProducts { get; } // Product is the POCO class
}

A concrete implementation of this repository based on EF would simply return an ObjectSet<Product> from the ObjectContext which the T4 template did create.

And your business layer runs a query this way:

IProductsRepository rep = new SomeConcreteImplementationOfProductsRepository();
IList productsOfCategory =
    rep.AllProducts.Select(p => p.Category == "stuff").ToList();

But if you want to be more open what kind of persistance storage you like to support it might be better to design the repository independent from IQueryable. The consequence could be that your abstract repository interface needs more specific methods to answer requests from the business layer, for instance you need now:

public interface IProductsRepository
{
    IList<Product> GetProductsOfCategory(string category);
}

and the business layer does this:

IProductsRepository rep = new SomeConcreteImplementationOfProductsRepository();
IList productsOfCategory = rep.GetProductsOfCategory("stuff");

A concrete implementation of this Repository using EF (or another data framework supporting LINQ) could still leverage a LINQ query like the business layer did in the first example. But other implementations could work in another way (say: you have a "database" which stores products in one text file per category. Then the implementation for that interface method would read one specific file from disk. Or your repository implementation asks a webservice for the data, and so on...)

Key point is: If you are using POCO classes you are open for all those kinds of repositories. EF with POCO support doesn't force you to build repository interfaces based on IQueryable or even IObjectSet. It finally depends on what kind of persistance layers you have in mind. The more different they are the more specific methods you might need to support in your repository interface and the more work you'll have to implement those methods. Using IQueryable is a comfortable compromise which allows to define a simple repository interface while enabling simple implementations by EF but also other databases with LINQ provider. I think that's the only reason why you see examples of repository pattern implementations with IQueryable so often. It's not an inherent restriction imposed by EF with POCOs.

(That's how I think about it, not being an expert in design patterns, so heavy attacks and corrections in the comments are welcome.)

Slauma
@Sluma. Thanks for taking time to write this up. Yes, I can have IList or something non-LINQ, non-EF etc. However, I guess my question didn't really talk about what the scope of a mapping framework is expected. O/R Mappers should be able to let caller traverse the object graph (as empty, hollow or incomplete it may be) and then the framework re-contructs and traverses platform as appropriate). So when I have IList, I cannot really query or traverse so transparently. ... contd.
... For Query, I've got LINQ to objects, and for traversing, I need to make sure I know when and where to plug the related objects -> these two things are why we use O/R mapping in the first place. Just for simple table to object mapping, heavy systems like EF are an overkill, IMO. ... cntd.
Really, from a caller's perspective: an O/R Mapper should give access to a node in the object graph and let the traversals commence without the need to go back to the O/R mapper much (possibly no need). From mapper interface implementation's perspective: all the needed framework elements, non-caller-exposed interfaces, abstract classes, etc. for someone to truly implement the O/R Mapping transparently. ...contd.
Persistence Ignorance has been tried for more than 2 decades and it ain't happening in our lifetime, but sure enough, we should be able to tuck away Persistence specifics outside of our object graphs and still be able to do more than table gateways and Repositories.