views:

1180

answers:

7

I'm trying to determine how best to architect a .NET Entity Framework project to achieve a nice layered approach. So far I've tried it out in a browse-based game where the players own and operate planets. Here's how I've got it:

Web Site

This contains all the front end.

C# Project - MLS.Game.Data

This contains the EDMX file with all my data mappings. Not much else here.

C# Project - MLS.Game.Business

This contains various classes that I call 'Managers' such as PlanetManager.cs. The planet manager has various static methods that are used to interact with the planet, such as getPlanet(int planetID) which would return an generated code object from MLS.Game.Data.

From the website, I'll do something like this:

var planet = PlanetManager.getPlanet(1);

It returns a Planet object from from the MLS.Game.Data (generated from the EDMX). It works, but it bothers me to a degree because it means that my front end has to reference MLS.Game.Data. I've always felt that the GUI should only need to reference the Business project though.

In addition, I've found that my Manager classes tend to get very heavy. I'll end up with dozens of static methods in them.

So... my question is - how does everyone else lay out their ASP EF projects?

EDIT

After some more though, there's additional items which bother me. For example, let's say I have my Planet object, which again is generated code from the wizard. What if a time came that my Planet needed to have a specialized property, say "Population" which is a calculation of some sort based on other properties of the Planet object. Would I want to create a new class that inherits from Planet and then return that instead? (hmm, I wonder if those classes are sealed by the EF?)

Thanks

A: 

I'm no expert, but that sounds pretty good to me. That similar to what I have in my solutions, except I just merge the EF project with the business project. My solutions aren't that big, and my objects don't require a lot of intelligence, so its fine for me. I too have a ton of different methods for each of my static helper classes.

If you don't want the presentation layer knowing about the data access layer, then you have to create some intermediary classes, which would probably be a lot of work. So whats the problem with your current setup?

SkippyFire
Dependencies make the testing and modification of individual layers more difficult. For a small project it's probably of little importance. But for projects of larger scale and lifetime it's usually recommended to have 0 dependencies between your layers via the use of a inversion of control container and defined interfaces. This is currently quite tricky to do with the Entity Framework generated classes.
Simon Brangwin
+3  A: 

You could try the following to improve things:

  • Use EF to fetch DTOs in your Data layer, then use these DTOs to populate richer business objects in your Business layer. Your UI would only then need to reference the Business layer.
  • Once you have created the rich business objects, you can begin to internalise some of the logic from the manager classes, effectively cleaning up the business layer.

I personally prefer the richer model over the manager model because, as you say, you end up with a load of static methods, which you inevitibly end up chaining together inside other static methods. I find this both too messy and, more importantly, harder to understand and guarantee the consistency of your objects at any given point in time.

If you encapsulate the logic within the class itself you can be more certain of the state of your object regardless of the nature of the external caller.

A good question by the way.

flesh
I like where your idea is going - however, wouldn't you be duplicating a lot of work? For example, if a DTO has various properties, you'll likely be creating all those properties again in your 'richer' version of the class. Right?
Chu
After additional though - have you ever made classes in your BLL layer that inherit from the DTO's in the Data Layer? This would enable some customization. Thoughts? Bad idea?
Chu
inheriting would increase coupling between layers (rather than reducing it) and you may end up with circular reference dependencies, which would scupper it anyway. Yes there would be some duplication but remember EF can generate your DTOs so i wouldnt worry too much about that..
flesh
It is of course always about personal preference and the nature of your specific project, but the 'win' for me is in scaling back the use of manager classes. They rarely feel right to me :)
flesh
+1  A: 

IMHO, your current layout is fine. It's perfectly normal for your UI to reference the 'Data' layer as you are calling it. I think that perhaps your concern is arising due to the terminology. The 'Data' you have described more often referred to as a 'business objects' (BOL) layer. A common layout would then be to have a business logic layer (BLL) which is your 'Managers' layer and a data access layer (DAL). In your scenario, LINQ to Entites (presuming you will use that) is your DAL. A normal reference pattern would then be:-

UI references BLL and BOL. BLL refences BOL and DAL (LINQ to Entites).

Have a look at this series of articles for more detail.

AdamRalph
I see your point. Although in the case of EF, I have no choice but to combine my BOL with the DAL since the BOL is generated by the wizard that makes the EF. Am I missing anything?
Chu
Sorry, mis-statement on my part. The EF is not your DAL. Whatever layer you use to get items out of the database will be your DAL, presumably LINQ to Entitites. In that case the model I describe still holds. Your generated BOL is still just a BOL, using the EF. I will edit the post.
AdamRalph
A: 

Your layout looks ok. I would have added a Utility/Common layer

Web UI
Business Layer
Dataobjects
Utilities layer

Kb
+2  A: 

As for your second question (after the EDIT) if you need or want to add features to your EF objects you can use partial classes. Right click the EDMX file and select view code.

Or if this isn't enough for you can ditch the designer and write your own EF enabled classes.

There is a (brief) discussion of both options here - http://msdn.microsoft.com/en-us/library/bb738612.aspx

Christopher Edwards
A: 

I would add DTOs to your Business layer that are "dumb object" representations (i.e. only properties) of the Entities in your data layer. Then your "Manager" classes can return them, such as:

class PlanetManager
{
    public static PlanetDTO GetPlanet(int id) { // ... }
}

and your UI can only deal with the BLL layer via POCOs; the Manager (what I would call a "Mapper" class) handles all the translating between the objects and the data layer. Also if you need to extend the class, you can have a "virtual" property on the DTO object and have the Manager translate that back to its components.

Wayne M
+1  A: 

As for your second question in the "EDIT" section:

If I'm not mistaken, the classes generated by EF are not sealed, and they are PARTIAL classes, so you could easily extend those without touching the generated files themselves.

The generated class will be:

public partial class Planet : global::System.Data.Objects.DataClasses.EntityObject
{
 ...
}

so you can easily create your own "PlanetAddons.cs" (or whatever you want to call it) to extend this class:

public partial class Planet 
{
 property int Population {get; set;} 
 ...
}

Pretty neat, eh? No need to derive and create artificial object hierarchies....

Marc

marc_s