谁应该创建业务对象?

时间:2015-04-20 09:31:59

标签: c# data-access-layer domain-model

由于业务/域对象应该不知道它们的持久性,因此它们显然不能包含从数据库加载数据以初始化自己的代码。

另一方面,并​​非业务对象的所有属性都具有公共setter来帮助封装并避免将它们设置为无效值。

这意味着当从数据库中提取数据时,没有其他类可以完全初始化业务对象。

由于以上所有都是常见的最佳做法,因此必须有一些解决方案。 那么谁应该负责构建业务对象并用数据库中的数据填充它们?

注意:我想到的唯一选择是将所有属性添加到构造函数中,这在我看来是非常不切实际的。

3 个答案:

答案 0 :(得分:2)

这个问题的解决方案很少。但两者都不是“完美的”。

  1. 使用反射设置私有字段或属性。大多数ORM使用此解决方案。问题可能是当ORM设置属性时,它有一些逻辑,导致实体的不合逻辑状态(我被这种情况烧了好几次)。
  2. 摘要“数据持久性”作为键/值映射。这样,实体可以自我保持并且仍然独立于特定的持久性技术。但是你仍然需要明确地对此进行编码。
  3. 构建器模式。具有相同属性的单独类,可以访问实体的私有字段,但仅用于构造。主要缺点是需要为每个实体建立构建器。
  4. 创建一个DTO,它反映实体的状态,但不是它的行为。然后,实体可以读取/创建此DTO以加载或保持自身。与上述相同的缺点。
  5. 我个人认为您的问题没有任何好的答案,除非您可以自动设法执行以前的解决方案之一。通过代码生成或通过语言支持。例如,对“构建器模式”提供语言支持会有很大帮助。

答案 1 :(得分:0)

存储库应该能够根据数据层提供的信息创建业务对象。逻辑是,由于存储库应该以一种隐藏用户实现的方式持久保存您传入的对象,因此它必须能够序列化和反序列化该对象而无需任何额外信息。

如果您拥有私有数据的对象,则通常的模式是通过构造函数传递私有信息。

应该可以在不调用存储库的情况下创建新对象。通常通过公共构造函数

例如:

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;
                    }
                }
            }
        }
    }

答案 2 :(得分:-1)

由于术语的原因,这可能会变得复杂 - 同一个事物通常可能有多个名称,或者一个模式可能是其他离散模式的合并。希望这个(非常简短的)答案对你有用。

您通常会有一个数据层(DAL)或“数据服务”,它的工作是与数据存储进行通信(或者它可以与存储库层或ORM进行通信)。

负责创建数据实体的层(“业务对象”)可能因您的设置而异。 ORM(如实体框架)可以返回数据实体,但是您通常希望在它们进入应用程序的其余部分之前将它们更改为更不可知的内容,这样就可以完成DAL(或特定数据)的工作。 service“)将它们从EF对象映射到常规数据实体。

或者,存储库层可以创建实体,因为它用于查询基础数据存储。