N-tier architecture: the best place to store business objects?

Say I have a three-tier architecture (user interface, business, and data). Usually I create a 4th project called β€œModel” or β€œGeneral” to save data access objects, and each of the other projects will use this project.

Now I am working on a project in which some of my data access objects have methods such as Save (), etc. that need access to the Data project. So, I would have a circular link if I tried to use the Model / Common project in a Data project.

In this scenario, where is the best place to store data access objects? I could save it in the Data project itself, but then my user interface project, which should know about data access objects, will have to access the data layer, which is not very good.

+4
source share
7 answers

This is what I have in my project.

1.) Application.Infrastructure

  • Base classes for all business objects, a business collection of objects, data access classes and my user attributes and utilities as extension methods. This defines the overall organization of the behavior of my last .net application.

2.) Application.DataModel

  • A typed dataset for a database.
  • TableAdapters are expanded to include transactions and other functions that I may need.

3.) Application.DataAccess

  • Data Access Classes.
  • The actual location where database actions are requested using a basic set of typed data.

4.) Application.DomainObjects

  • Business objects and collections of business objects.
  • Transfers

5.) Application.BusinessLayer

  • Provides manager classes accessible from the presentation layer.
  • HttpHandlers.
  • My own base page class.
  • More stuff here.

6.) Application.WebClient or Application.WindowsClient

  • My presentation level
  • Accepts links to Application.BusinessLayer and Application.BusinessObjects.

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

All my queries are determined only by Application.DataModel.

Application.DataAccess returns or accepts business objects as part of any data access operation. Business objects are created using reflection attributes. Each business object is marked with attribute mapping in the target table in the database, and properties in the business object are marked with attribute mapping to the target coloumn in the corresponding database table.

My validation structure allows me to validate each field using a designated ValidationAttribute.

My framrwork makes heavy use of attributes to automate most tedious tasks, such as matching and validation. I can also use the new feature as a new aspect in the framework.

A sample business object will 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) { } } 
+2
source

I do not think you have your own n-level. It looks like you are building more than two-tier systems.

In a real 3-level project, only your data level allows you to talk to the database. You have it with your "Model" or "Normal" projects. These projects are your data layer. But where you deviate, you only need to be allowed to speak only with a business level. Your presentation code should not allow you to talk to data-level projects at all.

n-Tier comes when you have more than 3 "levels", but the same principles: each level knows how to use (and requires only a link) under it, and then provides an api for the level above it. In my own projects, I take the typical level of presentation, business and data and provide a 4th level of translation between business and data. Thus, the data layer can return common types, such as dataset, datatable and datarow, and the business layer should work only in terms of strongly typed business objects. The translation layer only converts between shared data objects and strongly typed objects. Thus, a change in one of the traditional levels is less likely to require a change in the other.

+8
source

The data layer should store information in terms of rows and columns (possibly using typed DataSets if you want) if you use a relational backend. There are no "business objects."

The business layer should use your "business objects." It may have a link to the BusinessObjects project.

In short:

  • The user interface has links to Business and BusinessObjects
  • Business has links to BusinessObjects and Data li>

Hope this helps.

+1
source

I have a BusinessObjects project, server-side mappings (ORMs) and the corresponding DataAccess service are stored, exposing them to CRUD operations (as well as others like GetAll), etc.

+1
source

I would suggest creating and linking what you want in the model project and implementing this definition in the data layer. Thus, all three (four?) Projects can use this definition without knowing how it is implemented.

0
source

In my opinion, only the business layer should have knowledge about data access objects. He must use them for data operations, applying his own business rules and logic, and then return the mute objects (for example, data transfer objects) to the user interface level above.

You can use something like AutoMapper to automatically map data and business objects.

0
source

In fact, it depends on the template, if you use MVC (the template of the control controller), the model is a representation of data about the specific domain on which the application is running (usually using ORM), we use the DATA project for these classes.

Models are not objects of data access, so data access becomes in the form of repositories in another project. Services for business rules and, finally, a web project. With this approach, Data.dll is mentioned in all projects. The model is similar to the ubiquitous.

 DATA(Domain Model) -> REPOSITORY(Data Access) -> SERVICE(Business Rules) -> WEB 
0
source

All Articles