Using a custom layer to wrap EF objects

Dec 15, 2011 at 5:27 PM

Hi,

I'm working on an application that interacts with a rather messy and disorganized legacy database.  As a result, the data objects produced by the entity framework are also somewhat messy, with requirements on consistency that would not be enforced by the NakedObjects UI (e.g. some data is duplicated in multiple places, and some objects need to be updated and/or created whenever certain other objects are changed).

I'm wondering if it's possible to write an additional layer that accesses the entity framework to manage the data stored in the database, but provides a unified interface for NakedObjects to work with without having to worry about consistency issues?  And if it is possible, how would I go about setting this up?

Thanks

Jules

Dec 15, 2011 at 6:39 PM

So you generated your EF model from the DB then?

I have not done this myself, but if I understand correctly, EF has a logical model, as well as a storage model (I am not sure of the official / correct terms) and there is a mapping between the two. The logical model consists of your poco C# classes, and the storage model represents your database structure. When generated from the DB, these two are mostly the same, but that does not mean they have to be. You can greatly modify; rename entities, relationships, and also change the structure of the logical model, and still maintain a mapping to the storage model.

So I think EF already intrinsically has the capability you are looking for.

As I mentioned, this is theoretical knowledge for me to a great extent, as I have only made relatively small changes to the logical model. But google around a bit. This is independent of Naked Objects.

Hope that is of some help.

Coordinator
Dec 15, 2011 at 9:03 PM

As Jaques, says, you can do quite a lot within the Entity Model.  Not only can you do some hand mapping between the entity definitions and the table definitions, you can also attach stored procedures or database functions to the entities  -  in a way that is transparent to Naked Objects and shouldn't require you to write any special code outside of the database.  You need to dive down into EF.  Read Julia Lerman's book on EF, for example.  Another option is to consider using database views, which EF can also map (though I don't have any experience of doing this personally).

Editor
Dec 15, 2011 at 10:34 PM
You didn't mention what your database is, but (guessing that it's SQL Server), you can use views along with instead-of triggers, combined with code-first.

To flesh this out: pretend that there is no legacy database, and just design your entities as you think they should be. Then let NO/EF forward generate your database.

Then, write a script that drops those tables and replaces them with views against the legacy database tables. Where the view is implicitly read-only (eg is a join over multiple existing tables), then write an instead-of trigger to "post" the inserted/updated data to the relevant tables.

We've spiked this and it seems to work just fine with EF.

Cheers
Dan


On 15 December 2011 17:27, jh3141 <notifications@codeplex.com> wrote:

From: jh3141

Hi,

I'm working on an application that interacts with a rather messy and disorganized legacy database. As a result, the data objects produced by the entity framework are also somewhat messy, with requirements on consistency that would not be enforced by the NakedObjects UI (e.g. some data is duplicated in multiple places, and some objects need to be updated and/or created whenever certain other objects are changed).

I'm wondering if it's possible to write an additional layer that accesses the entity framework to manage the data stored in the database, but provides a unified interface for NakedObjects to work with without having to worry about consistency issues? And if it is possible, how would I go about setting this up?

Thanks

Jules

Read the full discussion online.

To add a post to this discussion, reply to this email (nakedobjects@discussions.codeplex.com)

To start a new discussion for this project, email nakedobjects@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com


Dec 17, 2011 at 8:52 AM

Thanks for the replies.

It does look as though EF is more capable than I at first thought it was -- an awful lot of the functions appear to be hidden away from the user interface in visual studio.  So if necessary, it looks like it *might* be possible to do it with a custom conceptual and mapping layer there, although I am still not certain it can do everything I need (it appears to have been designed from the perspective of undoing changes to the conceptual model introduced while normalising databases, while my problem is basically the opposite, a horribly-denormalised database that lacks even in basic niceties like foreign keys to link the tables).  My main concern here is that it seems like a lot of stuff to learn about, which is going to add at least days, if not actually weeks, to the time it would take to do this.  And if I get half way through and find it can't do something I need, that's wasted time.

What definitely would work, however, is the idea of using views & stored procedures.  My major problem with this, though, is that I don't know of a good way to test-drive this kind of solution.  I find TDD is pushing me farther & farther away from doing things like this in the database, because right from the beginning I'm working with tests that are isolated from the database...

I *do* know that I can develop an application logic layer that does this in C#.  I know everything I need to know to develop it, I'm happy with how to test it, and it seems an acceptable solution.  The question is, is it possible to then use that layer from NakedObjects, or is the NakedObjects framework so closely tied to EF that it would be impossible or impractical?

Coordinator
Dec 17, 2011 at 10:39 AM

The Naked Objects Framework is not coupled to EF at all - as evidenced by the fact that it supports separate in-memory and XML object stores as well as EF. So there is no reason at all why you couldn't write a new custom store that does what you want. I'd suggest you take a look at the existing EF store  to get an idea of what would be involved.

However having written a couple of object stores I would warn you that the NOF is an opinionated framework and getting it to play nicely with an ORM is not always trivial. So if you're going to try this I'd suggest you do a spike to make sure you understand what is involved. There is a persistor test suite so if you get that passing you should be 90% of the way there.

Finally though I would advise to use the EF capabilities rather than a custom persistor - NOF has XATs which allow you to write end-to-end tests - I see no reason why you shouldn't do TDD against the database using XATs.      

Coordinator
Dec 17, 2011 at 4:45 PM
Edited Dec 17, 2011 at 4:46 PM

 I have recently used Naked Objects to create an application running on top of a legacy database that, like yours, had no foreign keys.  For that particular system I chose to leave the Entity Model as it was generated from the database schema and do all the work of associations within the domain code, using a standard pattern for which I wrote a code snippet.  In the following code, the property Bar contains an integer that represents a row from the Bars table, but which is not constrained as an FK in the database, so EF does not recognise it as an association:

public class Foo {
  //Injected
  public IDomainObjectContainer Container{protected get; set;}
  //Foo's own value properties here.
  [Hidden] 
public int BarId{get; set;} //Key of Bar (but not an FK in the database)
  // Derived property
[NotPersisted] public Bar { get { if (bar == null) { bar =Container.Instances().Where(x =>x.Id == BarId).FirstOrDefault(); } return bar; } set { bar = value; BarId = bar.Id; } }
  //Cached reference to derived property
private Bar bar;
}

If you have a lot of associations like this within a single class then this pattern can result in a lot of chattiness  i.e. several round trips to the database to retrieve and render the instance of Foo.  But that all occurrs on the server before the view is returned to the user.  So in practice for the application I was working on, performance was fine.

It would, of course, be much better and more performant to create a clean entity model using e.g. the Views and Triggers approach that Dan described.  But in terms of speed of development and prototyping, this pattern is a very quick way to get going when constrained by a poor database schema.

Coordinator
Dec 17, 2011 at 4:57 PM

"My main concern here is that it seems like a lot of stuff to learn about, which is going to add at least days, if not actually weeks, to the time it would take to do this.  And if I get half way through and find it can't do something I need, that's wasted time."

However you write the system (i.e. not using Naked Objects) you have to deal with that challenge of the poor database schema.  Conventionally you would do this by writing a hand-crafted data mapping layer.  If you can get it going using EF as the data mapper then this is definitely an improvement over the former.  Ideally, you want to take the opportunity to create a proper logical model, both in EF and in the domain code.  Naked Objects is a very easy way to experiement with this, and gives you the huge added benefit of a first-cut UI for free.

None of this work would be wasted, even if you eventually decided to drop Naked Objects, or even drop EF.  If you changed the example code in my previous reply to delegate the retrieval of the associated object to an injected service of your own definition, then you could always replace the implementation (i.e. the lines such as:  Container.Instances().Where(x =>x.Id == BarId).FirstOrDefault();) with an implementation that went direct to the DBContext, or even with hand-crafted SQL statements.

My bet, though, is that you would find that Naked Objects did the job very well and you'd stick with it.  Indeed, the only way that I could persuade the Irish Government to make such a huge investment in the Naked Objects approach was by constantly reassuing them (in the early days this is  -  several years ago) that they could always re-use the domain model they were writing in a conventional architecture if the Naked Objects architecture proved too constraining.  Fortunately, it didn't.