Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I abstract Entity Framework away from my Entities?

I have a Foo entity in Entity Framework. But I'm making it inherit from IFoo so that my business logic only knows IFoo - thus abstracting Entity Framework away.

The problem is that Foo has a collection of Bar entities. And this collection is of type EntityCollection<Bar> .

If I put this collection in IFoo as it is, I make IFoo dependent on Entity Framework. So I thought of putting it as ICollection<IBar>, but this doesn't compile (naturally).

The only solution I can think of is to go to the concrete Foo implementation generated by the Entity Framework designer and change the collection from EntityCollection<Bar> to ICollection<IBar> there. But I dread the thought of the implications this will have on Entity Framework "behind the scenes".

Is there any way for me to define IFoo and IBar independently of Entity Framework while still maintaining Foo and Bar as EF Entities that implement them? Do IFoo and IBar even make sense, if I cannot achieve this independence that I aim for?

like image 201
urig Avatar asked Mar 29 '09 15:03

urig


People also ask

What is the key advantage of using Entity Framework?

What are the advantages of the Entity Framework? Entity Framework helps to reduce development time and development cost. It provides auto-generated code and allows developers to visually design models and mapping of databases. It allows easy mapping of Business Objects.

How does Entity Framework works internally?

The Entity Framework uses information in the model and mapping files to translate object queries against entity types represented in the conceptual model into data source-specific queries. Query results are materialized into objects that the Entity Framework manages.

What is the Java equivalent of Entity Framework?

The standard ORM API in Java it's called JPA, and is part of the Java EE specification. Another alternative would be to use Hibernate.

What is entity in Entity Framework in C#?

An entity in Entity Framework is a class that maps to a database table. This class must be included as a DbSet type property in the DbContext class. Entity Framework API maps each entity to a table and each property of an entity to a column in the database.


5 Answers

The general concept you are referring to is "persistence ignorance" (PI), although that generally applies directly to entities themselves rather than the code that consumes the entities.

In any case, Hibernate and NHibernate natively support PI, but the initial version of Microsoft's Entity Framework does not. MS caught a lot of flak for this and PI is probably the #1 most discussed feature for the next version (whenever that is).

As far as what you are trying to do with interfaces, does the collection of Bars need to be modified after it is retrieved? If the answer is yes, there is no easy answer. Even covariance couldn't help you here because ICollection<T> has an Add method.

If the collection is read-only, then you might consider exposing it as IEnumerable<IBar>. The Enumerable.Cast method makes this fairly convenient.

interface IFoo
{
    IEnumerable<IBar> Bars { get; }
}

partial class Foo : IFoo
{
    IEnumerable<IBar> IFoo.Bars
    {
        get { return Bars.Cast<IBar>(); }
    }
}

Also, I know of at least one effort to make the current version of EF support persistence ignorance.

like image 125
Daniel Pratt Avatar answered Oct 21 '22 19:10

Daniel Pratt


I'm a Java developer, so I can't comment with any authority on Entity Framework. I can tell you that ORM solutions like Hibernate make it possible to have POJO persistence without having to resort to common abstract classes, interfaces, or modifying byte code. It handles relationships like the 1:m you cite for your Foo and Bar without having to use special collection classes.

The special sauce is externalized into mapping configuration and Hibernate itself.

The little bit that I read about Entity Framework suggests that it's an ORM solution with the same aim: POCO persistence. I didn't see any mention of interfaces. I can't see the need for them from your example, because it's too abstract.

I'm inferring that it's possible to get that independence between business objects and persistence tier without having to resort to those interfaces, because I know Hibernate does it. I'd say that Spring's JDBC solution accomplishes it as well, because there's no need for common interfaces. They use a RowMapper construct to ferry data out of a query and into an object.

I wish I could advise you precisely how to do it with Entity Framework, but maybe you'll take heart knowing that it can be done.

like image 24
duffymo Avatar answered Oct 21 '22 19:10

duffymo


I recently wrote a comprehensive post about this: Persistence Ignorance in ADO.NET Entity Framework. You might want to look at EFPocoAdapter. That does just this and it will eventually deprecate into EF v2.

For what it's worth, I am using EFPocoAdapater and it's been working well for me.

like image 26
aleemb Avatar answered Oct 21 '22 19:10

aleemb


We've been doing the exact same thing for LINQ to SQL. I got around the collection issue by writing a class which wraps an IList and casts to and from the correct type as required. It looks a bit like this:

public class ListWrapper<TSource, TTarget> : IList<TTarget>
    where TTarget : class
    where TSource : class, TTarget
{
    private IList<TSource> internalList;

    public ListWrapper(IList<TSource> internalList)
    {
        this.internalList = internalList;
    }

    public void Add(TTarget item)
    {
        internalList.Add((TSource)item);
    }

    public IEnumerator<TTarget> GetEnumerator()
    {
        return new EnumeratorWrapper<TSource, TTarget>(internalList.GetEnumerator());
    }

    // and all the other IList members
}

EnumeratorWrapper similarly wraps an IEnumerator and performs the casting. In the LINQ to SQL partial classes we expose the property like this:

public IList<ICustomer> Foos
{
    get
    {
        return new ListWrapper<Foo, IFoo>(this.Foos_internal);
    }
}

Any changes to the exposed list will be performed on the internal EntitySet so they stay in sync.

This works well enough but my feeling is that this whole approach is more trouble than it's worth, I'm a huge NHibernate fan and a strong believer in P.I. but we've put in a LOT of extra effort doing this and haven't really seen any advantage. We use the repository pattern to abstract away the actual DataContext access which I would say is the key part of decoupling ourselves from LINQ to SQL.

like image 26
Jon M Avatar answered Oct 21 '22 18:10

Jon M


Use a partial class to seperate your logic and rules from the autogenerated EF objects. In the example below FooEntityObject class is split into two using the partial keyword. I've used this technique before with EF and LINQ to SQL. The partial classes can be stored in seperate files so if your regenerate your EF object again your custom code doesn't get overwriten.

interface IFoo
{
    public ICollection<IBar> GetBars();
}

public partial class FooEntityObject : IFoo
{
    public ICollection<IBar> GetBars()
    {
        // convert EntityCollection<Bar> into ICollection<IBar> here
    }
}


public partial class FooEntityObject
{
    EntityCollection<Bar> Bars{get;set;}
}
like image 25
Damien McGivern Avatar answered Oct 21 '22 19:10

Damien McGivern