域对象的责任

时间:2013-12-21 07:10:10

标签: c# oop domain-driven-design

我有一个域名,员工可以在其中拥有角色列表。还有一个新的角色添加功能..在添加新角色时,我们需要检查员工是否已经具有“VP”角色。如果它已经存在,则不应添加新角色。此逻辑需要存在于Employee Domain实体中。

我通过添加方法名IsNewRoleAllowed()来启动它,它将返回一个布尔值。如果是,则业务层将新角色插入数据库。

但为了更自然OO,我决定通过创建一个函数AddRole来改变Employee对象的责任。它将执行角色添加责任,而不是返回布尔值。

我通过接收Action<int, int>作为参数来实现上述目标。它工作正常。

问题

将DAL方法传递给实体是否正确?

更新

@ThomasWeller补充了我同意的重要观点......

  
      
  1. 有角色是BL的纯粹概念。它与DAL无关。

  2.   
  3. 在这种方法中,BL将具有驻留在DAL中的代码的依赖性。它(BL)甚至应该在DAL实际上不存在时起作用。

  4.   

但是,由于我没有使用ORM,我如何修改代码以像建议的方法一样工作?

参考

  1. Grouping IDataRecord individual records to a collection
  2. CODE

    域实体

    public class Employee
    {
        public int EmployeeID { get; set; }
        public string EmployeeName { get; set; }
        public List<Role> Roles { get; set; }
    
        //Add Role to Employee
        public int AddRole(Role role, Action<int, int> insertMethod)
        {
            if (!Roles.Any(r => r.RoleName == "VP"))
            {
                insertMethod(this.EmployeeID, role.RoleID);
                return 0;
            }
            else
            {
                return -101;
            }
        }
    
    
        //IDataRecord Provides access to the column values within each row for a DataReader
        //IDataRecord is implemented by .NET Framework data providers that access relational databases.
    
        //Factory Method
        public static Employee EmployeeFactory(IDataRecord record)
        {
            var employee = new Employee
            {
                EmployeeID = (int)record[0],
                EmployeeName = (string)record[1],
                Roles = new List<Role>()
            };
    
            employee.Roles.Add(new Role { RoleID = (int)record[2], RoleName = (string)record[3] });
            return employee;
    
        }
    }
    

    BusinessLayer.Manager

    public class EmployeeBL
    {
        public List<Employee> GetEmployeeList()
        {
            List<Employee> employees = EmployeeRepositoryDAL.GetEmployees();
            return employees;
        }
    
        public void AddRoleToEmployee(Employee emp, Role role)
        {
            //Don't trust the incoming Employee object. Use only id from it
            Employee employee = EmployeeRepositoryDAL.GetEmployeeByID(emp.EmployeeID);
            employee.AddRole<Employee>(role, EmployeeRepositoryDAL.InsertEmployeeRole);
            //EmployeeRepositoryDAL.InsertEmployeeRole(emp.EmployeeID, role.RoleID);
        }
    }
    

    DAL

        public static void InsertEmployeeRole(int empID, int roleID)
        {
            string commandText = @"INSERT INTO dbo.EmployeeRole VALUES (@empID, @roleID)";
    
            List<SqlParameter> commandParameters = new List<SqlParameter>()
                                                    {
                                                        new SqlParameter {ParameterName = "@empID", 
                                                                          Value = empID, 
                                                                          SqlDbType = SqlDbType.Int},
                                                        new SqlParameter {ParameterName = "@roleID", 
                                                                          Value = roleID, 
                                                                          SqlDbType = SqlDbType.Int}
                                                    };
    
    
            CommonDAL.ExecuteNonQuery(commandText, commandParameters);
    
        }
    

2 个答案:

答案 0 :(得分:1)

没有。拥有角色首先是BL的纯粹概念,它与DAL无关。此外,在您的方法中,BL将具有驻留在DAL中的代码的依赖性,这将是错误的方向。 BL应该是持久性不可知(即它不应该以任何方式依赖于DAL中会发生的事情 - 它甚至应该在DAL实际上不存在的情况下工作。)。此外,DAL的职责只是持久化对象 - 而不是处理驻留在内存中的任何集合。

尽量保持简单,只需:

public int AddRole(Role role)
{
    if (!Roles.Any(r => r.RoleName == "VP"))
    {
        Roles.Add(role.RoleName);
        return 0;
    }
    else
    {
        return -101;
    }
}

...在你的Employee课程中,让DAL处理所有与持久性相关的问题(如果使用ORM,它会进行级联更新)。

答案 1 :(得分:1)

  

将DAL方法传递给实体是否正确?

我避免将DAL逻辑注入我的域模型。

更新域实体(例如Employee)后,无需更新数据库。

常见的解决方案是:

  1. 加载实体以从DB更新到内存(Identity Map,PoEAA)。
  2. 在内存中创建/更新/删除实体
  3. 将所有更改保存到数据库
  4. 为了跟踪新的/脏/已删除的实体Unit of Work模式

    Unit of Work

    通常使用