2

我正在开发一个以 oracle 作为后端的 asp.net 项目。最初,我使用三层架构开发了这个应用程序,其中 UI 作为 aspx 页面,BLL 和 DAL 作为类库项目。我在 BLL 和 DAL 中都使用了静态类和方法。DAL 仅由具有 Select、Execute 和 ExecuteScalar 静态方法的单个类组成,它们接受 BLL 类转发的查询。

达尔

private static string connString = ""

private static OracleConnection conn;

public static OracleConnection OpenConn()
{
  if (conn==null)
  {
    conn = new OracleConnection(connString);
  }

  if (conn.State != ConnectionState.Open)
  {
    conn.Open();
  }

  return conn;
}

public static DataTable Select(string query)
{
  DataTable dt = new DataTable();
  OracleDataAdapter da = new OracleDataAdapter(query, OpenConn());
  da.Fill(dt);
  return dt;
}

public static void Execute(string query)
{
  OracleCommand cmd = new OracleCommand(query, OpenConn());
  cmd.ExecuteNonQuery();
}

public static int ExecuteScaler(string query)
{
  OracleCommand cmd = new OracleCommand(query, OpenConn());
  int id = Convert.ToInt32(cmd.ExecuteScalar());
  return id;
}

BLL 类调用此 DAL 的方式如下 Employee BLL

public static DataTable GetEmployees(int facilityid)
    {
        DataTable dt = new DataTable();
        string q = string.Format("SELECT * FROM ..");
        dt = OraDAL.Select(q);
        return dt;
    }


    public static DataTable AddEmployee(string name, , int departmentid , int employeeType)
    {
        DataTable dt = new DataTable();
        string q = string.Format("INSERT INTO ...");
        dt = OraDAL.Select(q);
        return dt;
    }

现在我正在重构应用程序。具有 BLL 和 DAL 的三层架构与类库项目相同,带有一个名为 Domain 的附加类库项目,以包含所有其他项目引用的域类。我使用这些类在层之间传输数据。这次将 DAL 类保持为静态,将 BLL 保持为普通类。我已将大部分功能(查询)移至 DAL。现在,DAL 拥有EmployeesDAL、DepartmentsDAL 等类以及包含Select、Execute 和ExecuteScalar 静态方法的通用类。

员工.cs

public class Employee
{
    public int Id { get; set; }

    public string Name { get; set; }

    public Department department { get; set; }

    public EmployeeType employeeType { get; set; }
}

员工DAL

public static List<Employee> GetEmployees(int departmentid)
    {
        if (departmentid > 0)
        {
            string query = string.Format("SELECT * FROM EMPLOYEES WHERE department='{0}')", departmentid);
            return GetCollection(OraDAL.Select(query));
        }

        return null;
    }

    public static Employee GetEmployee(int employeeid)
    {
        if (employeeid > 0)
        {
            string query = string.Format("SELECT * FROM PMS_EMPLOYEES WHERE Id='{0}'", employeeid);
            return GetSingle(OraDAL.Select(query));
        }

        throw new Exception("Employee id not valid");
    }

    public static int AddEmployee(Employee employee)
    {
        if (employee !=  null)
        {
            string query = string.Format("INSERT INTO PMS_EMPLOYEES (name, department, employee_type) VALUES ('{0}','{1}','{2}')", employee.Name, employee.department.Id, employee.employeeType.Id);
            return OraDAL.Execute(query);
        }

        throw new Exception("Values not valid");
    }

private static List<Employee> GetCollection(DataTable table)
    {
        List<Employee> employees = null;
        if (table != null)
        {
            if (table.Rows.Count > 0)
            {
                employees = new List<Employee>();
                foreach (DataRow row in table.Rows)
                {
                    employees.Add(ReadDataRow(row));
                }
            }
        }
        return employees;
    }

    private static Employee GetSingle(DataTable table)
    {
        if (table != null)
        {
            if (table.Rows.Count > 0)
            {
                DataRow row = table.Rows[0];
                return ReadDataRow(row);
            }
        }

        return null;
    }

    private static Employee ReadDataRow(DataRow row)
    {
        Employee employee = new Employee() 
        {
            Id=int.Parse(row["ID"].ToString()),
            Name=row["NAME"].ToString(),
            employeeType=EmployeeTypesDAL.GetEmployeeType(int.Parse(row["EMPLOYEE_TYPE"].ToString())),
            department=DepartmentsDAL.GetDepartment(int.Parse(row["DEPARTMENT"].ToString()))
        };

        return employee;
    }

员工BLL.cs

 public class EmployeesBLL
{
    public List<Employee> GetEmployees(int departmentid)
    {
        if (departmentid > 0)
        {
            return EmployeesDAL.GetEmployees(departmentid);
        }

        return null;
    }

    public int AddEmployee(Employee employee)
    {
        if (employee != null)
        {
            return EmployeesDAL.AddEmployee(employee);
        }

        throw new Exception("Employee cannot be null");
    }

帖子越来越长,但我希望您对情况有更好的了解。我在新设计中遇到了一些问题,让我问这个问题,这是做事的正确方法吗?因为主要目标是避免在不同层之间来回移动数据表。虽然这种新的逻辑编码方式太费时,但值得付出努力。业务层变得太薄了,因为他们提供的唯一服务似乎是从 DAL 调用类似的方法,我首先需要 BLL 吗?如果是的话,什么情况下可能需要单独的 BLL。

编辑

我在上述设计中注意到的一个问题是数据库调用的数量。调用太多,因为当一个对象被填充时,所有子对象也被填充,导致调用数据库。例如填充 Employee 对象将导致填充部门实例。在大多数情况下,我只需要部门 ID 而不是整个部门的信息。

4

2 回答 2

1

展示层

你已经知道了。这是你的用户界面。它由视图、视图模型和(控制器/演示者)组成。此表示层仅具有与 UI 相关的逻辑(定位、css 样式等)。它不知道 BLL 的实现(只是接口),并且根本不知道 DAL(存储)。

业务层

您的业​​务逻辑所在的位置。每个选择操作、计算、验证、插入操作、删除、更新操作都属于这里。它不了解 UI,因此它可以在任何 UI 中工作,无论是 Web/桌面/移动应用程序,都具有相同的业务逻辑。这意味着在这一层中,没有使用明显的缓存/会话。相反,您可以将其包装在某个界面中。它不知道 storage,这意味着您需要另一层来进行存储,它是 DAL

数据访问层

这一层只是简单地对存储(平面文件、数据库、Web 服务、xml、json 等)进行 CRUD 操作,并返回对象模型。就这样。它不知道 UI 也不知道业务规则。此层的目的是使其易于更换。假设您需要将存储从数据库替换为 xml,这是层的工作,其他层保持不变。

回答你的问题

希望您已经知道 3 层的目的。

现在假设您在您的情况下使用带有 BLL 的 3 层:

  1. 对员工存储的任何更改都不会影响 BLL 和 UI
  2. 对业务逻辑(新搜索参数)的任何更改都会影响 DAL
  3. 您的 BLL 不知道数据访问(连接/数据库上下文等),这意味着它根本不需要知道连接
  4. BLL 的其他明显映射

现在假设您使用的是没有 BLL 的 2 层:

  1. 对员工存储的任何更改都不会影响 UI(无 BLL)
  2. 对业务逻辑(新搜索参数)的任何更改都会影响 DAL
  3. 你的 UI 知道 DAL。如果您将其设计为单独的项目,则会添加参考并打破分层。这为您的 UI 提供了直接访问其他 DAL 的机会。

是的,在您的情况下使用 BLL 是相当无用的,因为您只能将 UI 和 DAL 分开。但这就是3层的意义不是吗?

也就是说,如果您使用的是存储过程选择。您真正需要的是 DAL 中的通用存储库模式,这将在 BLL 访问期间为您提供很大帮助。

于 2013-06-03T07:04:00.780 回答
1

三层架构各部分的目的如下:

1. 用户界面

允许用户与您的域模型进行交互

2.领域模型/中间层

包含您的特定领域或业务流程到代码的翻译。代表您的特定业务问题或环境。该层应包含应用程序的所有业务规则和业务对象。

3.数据访问层

允许将您的域模型对象持久保存到数据存储中并从中检索。数据访问层简单地从持久数据存储(即数据库)中获取数据并将其转换为域模型对象,然后获取域模型对象并将它们持久保存到数据存储中。

在这三个领域中,我认为迄今为止最重要的领域是领域模型/中间层。这是您的应用程序的核心和灵魂,也是应用程序实际解决特定业务问题并为将使用您的软件的组织提供价值的地方。其他两个区域的目的只是将您的域模型公开给用户(UI)或允许检索或存储它(数据层)。

这意味着您应该努力将尽可能多的精力花在域模型/中间层上。这是您解决组织的特定业务问题的地方,也是您可以真正为公司或客户增加价值的地方。

在将这一一般原则应用于您的特定情况时,我有以下评论/建议。

  1. 您正在手动创建数据访问层和手工制作 SQL 语句。一般来说,这是对您时间的非常低价值的使用。有许多对象关系映射器(ORM) 工具,例如nHibernate实体框架,它们将负责从数据存储加载域模型对象并将对象持久保存回所需的低级管道。数据存储。我想你可能想调查这些。我认为使用这些 ORM 工具之一的解决方案将是比您建议的任何一个选项更好的解决方案。

  2. 根据您发布的代码,您的域模型/中间层只是一组属性,没有业务逻辑或业务规则。如果真的是这样,那就应该是这样。但是,最好利用您的时间与您的利益相关者交谈,并真正努力在域模型中对他们的流程进行建模,因为这是您可以最好地为您的组织增加价值的地方。

我知道这有点啰嗦,但希望它对你有帮助。

于 2013-06-02T14:36:13.867 回答