Home
Help
Register
Log in

Search

 
   Active Threads  

You are here: Home > LLBLGen Pro > Architecture> Entity Managers and Helpers - Guidance and Experience
 

Pages: 1
Architecture
Entity Managers and Helpers - Guidance and Experience
Page:1/1 

  Print all messages in this thread  
Poster Message
TrickOfTheMind
User



Location:

Joined on:
08-Nov-2007 00:27:08
Posted:
34 posts
# Posted on: 06-Jun-2008 03:17:30.  
I gradually refactoring from having my service facade contain loads of BL, essentially near everything bar the DAL/LLBLGen.

I start moving stuff into managers however it feel unnatural because in there seems to be multiple concerns:

class CustomerManager
{
     CustomerEntity GetCustomerById(string ID);
     CustomerEntity GetCustomerByName(string Name);
    
     UpdateLoyaltyPointsr(CustomerEntity customer)
    
}


In the first two methods I'm getting a customer Entity, in the third method I'm passing this back. Is this how managers should work, or should we have seperate managers (or suggest naming conventions) for wrappers and utilities

e.g.

class CustomerTaskManager
{
        (ctor)CustomerTask (CustomerEntity entity)


     UpdateLoyaltyPointsr();
}

class CustomerManager
{
     CustomerEntity GetCustomerById(string ID);
     CustomerEntity GetCustomerByName(string Name)
}

and then do

CustomerEntity selectedCustmer = customerManagerInst.GetCustomerByName("Frans");
CustomerTaskManager selectedCustomerTasks = new CustomerTaskManager(selectedCustomer);
selectedCustomerTasks.UpdatedLoyaltyPoints();


Discuss Dissapointed
  Top
stefcl
User



Location:
Switzerland
Joined on:
23-Jun-2007 19:52:49
Posted:
210 posts
# Posted on: 10-Jun-2008 08:15:45.  
Hello,

In my case, I have decided to create two different classes per entity. One that contains the typical CRUD stuff (CustomerManager) and an another with only business methods.

I started with only one class but it quickly became a bit bulky.


  Top
tprohas
User



Location:
Tucson, AZ
Joined on:
23-Mar-2004 00:00:43
Posted:
257 posts
# Posted on: 13-Jun-2008 19:59:03.  
Hello all,

I'll say that in my case I chose to do this all in one Manager class per subject. So I did something like the following.

CustomerManager()
EmployeeManager()
ProductManager()
OrderManager()
.CalculateShipping(OrderEntity order)
.GetCustomerOrders(CustomerEntity customer)

Then for perisistance I did this.

PersistanceManager()
.SaveEntity
.SaveEntityCollection
...

I did choose the mix the business logic with the fetch logic in one class even though it did tend to make the classes big. I liked being able to get at everything related to a subject in one place.
Aaron Prohaska
http://www.verdesoft.com/
 
Top
tprohas
User



Location:
Tucson, AZ
Joined on:
23-Mar-2004 00:00:43
Posted:
257 posts
# Posted on: 16-Jun-2008 21:25:22.  
I just want to add to my last message and say this.

I've now used this architecture on a number of small web applications. It seems to work well and I like working with it. I don't however know how good a design it really is. The largest web application I've used it with was the Wrench Science web site (http://www.wrenchscience.com/). This site receives around 2000 unique visits a day with a very small number of employees using the web admin site for manager the business. So far there have not been any performance issues with it.

That being said I would love to get the opinions of other who know more about software architecture then I do on the followign design.

I generally break my architecture into the following assemblies.

Company.Division.LLBLGen
Company.Division.LLBLGenDBSpecific

I then using the above assemblies in my business logic layer assembly.

Company.Division.AppServices

The AppService assembly then contains the following (simplistic example).

ServiceManager
The ServiceManager class contains static methods for creating instances of manger classes.

PersistanceManager
The PersistanceManager class contains instance methods for saving, deleting and any other persistance related logic.

ProductManger
The Product Manger class contains instance methods for fetching entities and performing business logic related to the entities.

Here is an example of actual code.

ServiceManager
Code:

public class ServiceManager
{
    public ServiceManager()
    {
        //
    }

    public static PersistanceManager GetPersistanceManager()
    {
        string connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ToString();
        return new PersistanceManager(connectionString);
    }

    public static ProductManager GetProductManager()
    {
        string connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ToString();
        return new ProductManager(connectionString);
    }
}


PersistanceManager
Code:

public class PersistanceManager
{
    private string connectionString = string.Empty;

    public PersistanceManager(string connectionString)
    {
        this.connectionString = connectionString;
    }

    #region public bool SaveEntity(IEntity2 entity)
    /// <summary>
    ///
    /// </summary>
    /// <param name="entity"></param>
    /// <returns></returns>
    public bool SaveEntity(IEntity2 entity)
    {
        bool saved = false;

        using (DataAccessAdapter adapter = new DataAccessAdapter(this.connectionString))
        {
            saved = adapter.SaveEntity(entity);
        }

        return saved;
    }
    #endregion

    #region public int SaveEntityCollection(IEntityCollection2 collection, bool refetch, bool recursive)
    /// <summary>
    ///
    /// </summary>
    /// <param name="collection"></param>
    /// <param name="refetch"></param>
    /// <param name="recursive"></param>
    /// <returns></returns>
    public int SaveEntityCollection(IEntityCollection2 collection, bool refetch, bool recursive)
    {
        int affectedRows = 0;

        using (DataAccessAdapter adapter = new DataAccessAdapter(this.connectionString))
        {
            affectedRows = adapter.SaveEntityCollection(collection, refetch, recursive);
        }

        return affectedRows;
    }
    #endregion

    #region public bool SaveEntity(IEntity2 entity, bool refetchAfterSave)
    /// <summary>
    ///
    /// </summary>
    /// <param name="entity"></param>
    /// <param name="refetchAfterSave"></param>
    /// <returns></returns>
    public bool SaveEntity(IEntity2 entity, bool refetchAfterSave)
    {
        bool saved = false;

        using (DataAccessAdapter adapter = new DataAccessAdapter(this.connectionString))
        {
            saved = adapter.SaveEntity(entity, refetchAfterSave);
        }

        return saved;
    }
    #endregion

    #region public int UnitOfWorkCommit(UnitOfWork2 uow, bool autoCommit)
    /// <summary>
    ///
    /// </summary>
    /// <param name="uow"></param>
    /// <param name="autoCommit"></param>
    /// <returns></returns>
    public int UnitOfWorkCommit(UnitOfWork2 uow, bool autoCommit)
    {
        int affectedRows = 0;

        using (DataAccessAdapter adapter = new DataAccessAdapter(this.connectionString))
        {
            affectedRows = uow.Commit(adapter, autoCommit);
        }

        return affectedRows;
    }
    #endregion
}


ProductManager
Code:

public class ProductManager
{
    private string connectionString = string.Empty;

    public ProductManager(string connectionString)
    {
        this.connectionString = connectionString;
    }

    public EntityCollection<ProductEntity> GetProducts()
    {
        EntityCollection<ProductEntity> results = new EntityCollection<ProductEntity>();

        SortExpression sort = new SortExpression();
        sort.Add(ProductFields.Name | SortOperator.Ascending);

        using (DataAccessAdapter adapter = new DataAccessAdapter(this.connectionString))
        {
            adapter.FetchEntityCollection(results, null, 0, sort);
        }

        return results;
    }

    public ProductEntity GetProduct(int productId)
    {
        ProductEntity entity = new ProductEntity(productId);

        using (DataAccessAdapter adapter = new DataAccessAdapter(this.connectionString))
        {
            adapter.FetchEntity(entity);
        }

        return entity;
    }
}


This can then be used in the following way.

Code:

EntityCollection<ProductEntity> products = ServiceManager.GetProductManager().GetProducts();

// Use entity collection for a data source.

ProductEntity product = ServiceManager.GetProductManager().GetProduct(1);

// Make changes to product.
product.Name = "My new name";

bool saved = ServiceManager.GetPersistanceManager().SaveEntity(product);


Any advice or comments on this would be greatly appreciated.


Aaron Prohaska
http://www.verdesoft.com/
 
Top
Otis
LLBLGen Pro Team



Location:
The Hague, The Netherlands
Joined on:
17-Aug-2003 18:00:36
Posted:
37645 posts
# Posted on: 25-Jun-2008 09:30:13.  
There's one rule to know: there's no silver bullet. This means: if you ask someone if your design is good, that someone can't answer that question, simply because 'what's good?'. So if that someone answers the question still, it will be an answer which is based on what the person prefers.

If your design works great for you, if the code is maintainable, the users are happy, your design worked. If you see problems in these areas, change the design to fix these problems. That's more or less all there's to be said about this. One could say: "Use a webservice" or "Use remoting" or "use more tiers" but that's all not really adding anything valuable: most time of a project is spend on maintenance. If the maintenance of the code is easy, doable and practical, you've done it right. If the application works well, and the users are happy, why would there be a problem? I mean: if you would do the design differently and maintenance is also good, performance is OK and the users are happy, what's different? Regular Smiley
Frans Bouma
LLBLGen Pro / ORM Profiler Lead Developer | Blog | Twitter
 
Top
tprohas
User



Location:
Tucson, AZ
Joined on:
23-Mar-2004 00:00:43
Posted:
257 posts
# Posted on: 25-Jun-2008 09:34:28.  
Regular Smiley

Thank you Otis. That's a good answer to me. I guess that means that there also isn't anything obviously wrong about it which makes me feel like I did my research well.

Enjoy


Aaron Prohaska
http://www.verdesoft.com/
 
Top
Pages: 1  


Powered by HnD ©2002-2007 Solutions Design
HnD uses LLBLGen Pro

Version: 2.1.12172008 Final.