Who should create business objects?

Since business / domain objects do not need to be persistent, they obviously should not contain code that loads data from the database for initialization.

On the other hand, not all business object properties have public setters to aid encapsulation and avoid setting invalid values.

This means that no other class can fully initialize the business object when its data is retrieved from the database.

Since all of the above are common best practices, there should be some solution to this problem. So who should be responsible for building the business objects and populating them with data from the database?

Note. The only option that comes to my mind is to add all properties to the constructor, which in my opinion would be very impractical.

+3


source to share


3 answers


There are few solutions to this problem. But none of them are "perfect".

  • Use reflection to set private fields or properties. Most ORMs use this solution. The problem could be when the ORM sets a property that has some logic on it, which results in an illogical object state (I got burned by this quite a few times).
  • Ditch "saving data" as a key / value map. Thus, the object can be preserved and still does not depend on a specific conservation technology. But you still need to explicitly code it.
  • Drawing Builder. Share a class with the same properties that can access the private fields of an object, but are only used in construction. The main disadvantage is the need to create a builder for each object.
  • Create a DTO that reflects the state of the object, but not the behavior. The object can then read / create this DTO for loading or saving. Same flaw as above.


I personally don't see any good answer to your question unless you manage to do one of the previous solutions automatically. Either code generation or language support. For example, language support for a "builder pattern" will help a lot.

+2


source


The repository must be able to create a business object from the information provided by this directory. The logic is that since the repository should store the object you passed in in a way that hides the implementation from the user, it should be able to serialize and deserialize that object without additional information.

the general pattern, if you have a private data object, must have the private information passed through the constructor.

Creating new objects should be possible without calling the repository. Usually via a public constructor



eg:

public class Model {
        public String Id {get;set;}
        public String Colour { get; set; }

        public Model(String id, String colour)
        {
            this.Id = id;
            this.Colour = colour;
        }
    }

    public interface IRepository
    {
        void Add(Model item);
        Model Get(string id);
    }

    public class RepositorySql : IRepository
    {
        private string constr;
        public RepositorySql(string connstr)
        {
            this.constr = connstr;

        }
        public void Add(Model item)
        {
            using (SqlConnection conn = new SqlConnection(constr))
            {
                conn.Open();
                using (SqlCommand cmd = new SqlCommand("insert into table (userid,colour) values (@userid,@colour)", conn))
                {
                    cmd.Parameters.AddWithValue("@id", item.Id);
                    cmd.Parameters.AddWithValue("@colour", item.Colour);
                    cmd.ExecuteNonQuery();
                }
            }
        }


        public Model Get(string id)
        {
            using (SqlConnection conn = new SqlConnection(constr))
            {
                conn.Open();
                using (SqlCommand cmd = new SqlCommand("select * from table where id=@id)", conn))
                {
                    cmd.Parameters.AddWithValue("@id", item.UserId);
                    SqlDataReader dr  =cmd.ExecuteReader();

                    if (dr.Read())
                    {
                        Model i = new Model(dr["id"].ToString(), dr["colour"].ToString());
                        return i;
                    }
                    else
                    {
                        return null;
                    }
                }
            }
        }
    }

      

0


source


This can be complicated by terminology - there can often be multiple names for the same, or one template can be combined with other discrete templates. Hope this (very short) answer makes sense to you.

Typically you have a data layer (DAL) or "data service" whose job it is to talk to the data store (alternatively it can talk to the repository or ORM layer).

The layer responsible for creating data objects ("business objects") may differ depending on your installation. An ORM (like Entity Framework) can return data entities to you, but you generally want to change them to something more agnostic before they get into the rest of your application, so this would work with DAL (or specific data) service ") to map them from EF objects to regular data objects.

Alternatively, the repository layer can create objects as it is used to query the data store.

-1


source







All Articles