views:

239

answers:

5

What is the "best practice" for designing ascx user controls regarding separating the UI from the Data Access? Should my user control use 3 tier archetecture as in my projects or can I do the data acess from within the user control?

A: 

I would definitely suggest to access data from some kind of business layer. UI never should access databases directly.

  • What if your access rules changed?
  • What if your storage changed?
  • Can you ensure, that every UI control is able to enforce business rules?
  • etc.
Arthur
+1  A: 

You should never access the database from a user control. You should create a class for accessing the database, and everything within your application should use that class. Basically, the methods in the class would be wrappers around your stored procedure calls, but all that the application (and therefore user controls) sees is a method with the needed parameters. No knowledge of the database from the application's point of view. That allows you to make changes to the database without changing your application.

This link might help you:

http://www.simple-talk.com/dotnet/.net-framework/.net-application-architecture-the-data-access-layer/

Gabriel McAdams
Good link article. Good comments. Thanks.
Lill Lansey
A: 

This is what I have in my project.

1.) Application.Infrastructure

  • Base classes for all businessobjects, busines object collection, data-access classes and my custom attributes and utilities as extension methods, Generic validation framework. This determines overall behavior organization of my final .net application.

2.) Application.DataModel

  • Typed Dataset for the Database.
  • TableAdapters extended to incorporate Transactions and other features I may need.

3.) Application.DataAccess

  • Data access classes.
  • Actual place where Database actions are queried using underlying Typed Dataset.

4.) Application.DomainObjects

  • Business objects and Business object collections.
  • Enums.

5.) Application.BusinessLayer

  • Provides manager classes accessible from Presentation layer.
  • HttpHandlers.
  • My own Page base class.
  • More things go here..

6.) Application.WebClient or Application.WindowsClient

  • My presentation layer
  • Takes references from Application.BusinessLayer and Application.BusinessObjects.

Application.BusinessObjects are used across the application and they travel across all layers whenever neeeded [except Application.DataModel and Application.Infrastructure]

All my queries are defined only Application.DataModel.

Application.DataAccess returns or takes Business objects as part of any data-access operation. Business objects are created with the help of reflection attributes. Each business object is marked with an attribute mapping to target table in database and properties within the business object are marked with attributes mapping to target coloumn in respective data-base table.

My validation framework lets me validate each field with the help of designated ValidationAttribute.

My framrwork heavily uses Attributes to automate most of the tedious tasks like mapping and validation. I can also new feature as new aspect in the framework.

A sample business object would look like this in my application.

User.cs

[TableMapping("Users")]
public class User : EntityBase
{
    #region Constructor(s)
    public AppUser()
    {
        BookCollection = new BookCollection();
    }
    #endregion

    #region Properties

    #region Default Properties - Direct Field Mapping using DataFieldMappingAttribute

    private System.Int32 _UserId;

    private System.String _FirstName;
    private System.String _LastName;
    private System.String _UserName;
    private System.Boolean _IsActive;

    [DataFieldMapping("UserID")]
    [DataObjectFieldAttribute(true, true, false)]
    [NotNullOrEmpty(Message = "UserID From Users Table Is Required.")]
    public override int Id
    {
        get
        {
            return _UserId;
        }
        set
        {
            _UserId = value;
        }
    }

    [DataFieldMapping("UserName")]
    [Searchable]
    [NotNullOrEmpty(Message = "Username Is Required.")]
    public string UserName
    {
        get
        {
            return _UserName;
        }
        set
        {
            _UserName = value;
        }
    }

    [DataFieldMapping("FirstName")]
    [Searchable]
    public string FirstName
    {
        get
        {
            return _FirstName;
        }
        set
        {
            _FirstName = value;
        }
    }

    [DataFieldMapping("LastName")]
    [Searchable]
    public string LastName
    {
        get
        {
            return _LastName;
        }
        set
        {
            _LastName = value;
        }
    }

    [DataFieldMapping("IsActive")]
    public bool IsActive
    {
        get
        {
            return _IsActive;
        }
        set
        {
            _IsActive = value;
        }
    }

    #region One-To-Many Mappings
    public BookCollection Books { get; set; }

    #endregion

    #region Derived Properties
    public string FullName { get { return this.FirstName + " " + this.LastName; } }

    #endregion

    #endregion

    public override bool Validate()
    {
        bool baseValid = base.Validate();
        bool localValid = Books.Validate();
        return baseValid && localValid;
    }
}

BookCollection.cs

/// <summary>
/// The BookCollection class is designed to work with lists of instances of Book.
/// </summary>
public class BookCollection : EntityCollectionBase<Book>
{
    /// <summary>
    /// Initializes a new instance of the BookCollection class.
    /// </summary>
    public BookCollection()
    {
    }

    /// <summary>
    /// Initializes a new instance of the BookCollection class.
    /// </summary>
    public BookCollection (IList<Book> initialList)
        : base(initialList)
    {
    }
}
this. __curious_geek
Very nice answer, but he wasn't asking for an entire project, but for a single user control.
Jason Berkan
Agreed but this might give him a way to look at bigger picture.
this. __curious_geek
+1  A: 

Now matter how simple or complex a project, at the very least, all should be separated into a Presentation Layer, Business Layer, and Data Layer. At any given time any one of the three could change without affecting the others.

A user control is part of the presentation layer, it should supply data and user actions to the business layer which in turn interprets the data and those actions to make decisions. If necessary the business layer would call the Data Layer. The Data Layer in turn would handle all communication with the database/source files.

It's not that hard to separate the three and keep them separate.

SLoret
A: 

You need at a minimum, a 2 layer solution: data, then everything else. For a more complex project, you need to take that everything else and abstract it out into presentation, logic, data. Data can also be separated into data access and data model layers.

James