Architecture 我的业务逻辑应该如何与我的数据层交互?

Architecture 我的业务逻辑应该如何与我的数据层交互?,architecture,Architecture,所以我正在起草我的计划 这是我的计划: GUI --- Business Logic --- Data 您应该能够更换GUI或Data层而不会出现问题。 每一层都在观察自己。因此GUI将从businesslogic调用方法,这些方法将始终返回一个状态,可能还返回一些数据。GUI应如何响应数据,始终应由GUI层决定。业务逻辑对此不应有影响。 因此,解决了与GUI和业务逻辑的关系。 我希望你能跟我来 现在来看看更具体的东西。 我的数据层计划是使用数据库。 现在,业务逻辑应该如何从数据层调用方法 也

所以我正在起草我的计划

这是我的计划:

GUI
---
Business Logic
---
Data
您应该能够更换
GUI
Data
层而不会出现问题。 每一层都在观察自己。因此
GUI
将从
businesslogic
调用方法,这些方法将始终返回一个状态,可能还返回一些数据。GUI应如何响应数据,始终应由GUI层决定。业务逻辑对此不应有影响。 因此,解决了与GUI和业务逻辑的关系。 我希望你能跟我来

现在来看看更具体的东西。 我的数据层计划是使用数据库。 现在,业务逻辑应该如何从数据层调用方法

也许我应该创建一个枚举,对应于数据层知道的不同硬编码SQL查询

例如

作为枚举的查询

如果这是正确的方法,那么GetResults应该返回什么?字符串数组?但是如果查询有多维数据呢

那么我应该有2个泛型方法吗

Datalayer.GetSingleDimensionResults(SingleDimensionQueries.GetAllCustomersIDs);
Datalayer.GetMultipleDimensionResults(MultiDimensionQueries.GetAllCustomers);
或者我应该为每种类型的数据请求进行查询吗

Datalayer.GetAllCustomerIDs;
DataLayer.GetAllCustomers;

等等。

您的数据“层”可能不仅仅是一组语义查询,您应该将其封装在API中,否则您的业务逻辑层将不得不对数据层的实现了解太多。您在GUI和业务逻辑层之间使用的相同推理应该适用,并且出于相同的目的。

一般来说,我用来做的是:

数据层:

对于数据访问,我为每个对象创建了一个接口。每个接口都列出了相关对象的所有公共数据访问方法。为了保存数据,我还为每个对象创建了容器类型,这些容器类型可以是结构或仅包含数据的简单类。我还依赖于语言数据集(如列表)来保存数据,因此我没有链接到特定的数据库类型。在那之后,我创建了一个实现数据接口的类,这个类拥有所有的SQL和访问数据库的权限,因此在数据存储技术发生变化的情况下,这是唯一会被改变的类

业务层:

所有的逻辑都与数据有关,如何验证,数据接口中的哪些方法应该被调用,以及调用的顺序。此类使用容器(例如列表)接收数据并将数据“发送”到数据存储或GUI,其中数据类型是上面提到的my容器

图形用户界面:

调用业务逻辑方法并显示/格式化数据表示。除了调用业务逻辑的正确方法之外,这里没有其他逻辑

容器(C#)的小代码示例

//部门类数据访问接口。数据存储组件
命名空间数据存储
{
公共接口IDepartmentDS
{
void Open();//打开数据连接
void Close();//关闭数据连接
List();//获取所有部门(从数据库)
}
}
//此类保存一个部门的所有数据。这里没有逻辑。存储库程序集
命名空间存储库
{
公共课系
{
[可浏览(错误)]
公共部门()
{
}
[可浏览(错误)]
公共部门(字符串符号、字符串名称)
{
这个符号=符号;
this.DeptName=名称;
}
公共部门(部门)
{
this.Symbol=部门.Symbol;
this.DeptName=department.DeptName;
}
[可浏览(错误)]
公共字符串符号{get;set;}
公共字符串DeptName{get;set;}
}
}
//这个类本身实现了数据操作,访问真实的数据库。
//但是,此类之外的数据交换是通过存储库和类完成的
//泛型-主要列出
公共类数据存储:IDepartmentDS
{
//这里我用一般函数来连接数据库,格式存储
//程序参数清单等。
//部门界面列表方法declare的实现
List IDepartmentDS.List()
{
String query=String.Format(“从{0}中选择*”,DepartmentTable);
int行=0;
DataSet ds=ExecSqlCommand(查询,输出行);//此方法对此类是私有的
如果(ds==null)
返回null;
列表=新列表();
foreach(ds.Tables[0].行中的DataRow行)
{
list.Add(newrepositories.Department((String)行[DepFN_Symbol],(String)行[DepFN_DepName]);
//DepFN_符号和其他符号只是表示列索引的常量变量
}
退货清单;
}
}
公共类部门逻辑
{
公共部门逻辑
{
.....
}
公共列表GetAllDepartments()
{
//这里我创建了一个DataStorage的实例,但使用的是Department接口
//因此,我只限制对部门数据方法的访问。这可能是一个好方法
//这里的想法是使用工厂模式。
IDepartmentDS department=(IDepartmentDS)新数据存储();
部门开放(;
List departments=department.List();
部门关闭();
返回部门;
}
}
这个业务逻辑示例确实非常简单,它只展示了如何从存储层检索数据,但只要您有权访问数据,就可以按照您想要的方式对其进行操作。这里只是一个评论:如果在一个有数千个请求的非常繁忙的服务器上实现,可能应该重新考虑这个解决方案,因为它会占用大量内存

用于业务逻辑和用户界面
Datalayer.GetAllCustomerIDs;
DataLayer.GetAllCustomers;
    //Interface for Department class data access. DataStorage assembly

    namespace DataStorage
    {
        public interface IDepartmentDS
        {
            void Open();  //Open data conection
            void Close(); //Close data conection
            List<Repositories.Department> List(); //Gets all departments (from data base)
        }
    }


    //This class holds all data regarded a department. There's no logic here. Repositories assembly

    namespace Repositories
    {
        public class Department
        {
            [Browsable(false)]
            public Department()
            {
            }

            [Browsable(false)]
            public Department(String Symbol, String Name)
            {
                this.Symbol = Symbol;
                this.DeptName = Name;
            }

            public Department(Department department)
            {
                this.Symbol = department.Symbol;
                this.DeptName = department.DeptName;
            }

            [Browsable(false)]
            public String Symbol { get; set; }

            public String DeptName { get; set; }
        }
    }


    //This class implements the data manipulation itself, accessing the real database.
    //However the data exchange outside this class is done via repositories classes and 
    //Generics - Lists mainly

    public class DataStorage : IDepartmentDS
    {
       //Here I use to put generic functions to connect with the database, format stored
       //procedure parameters list etc.

       //Implementation of the List method declare in the Department Interface
           List<Repositories.Department> IDepartmentDS.List()
            {
                String query = String.Format("SELECT * FROM {0}", DepartmentTable);
                int rows = 0;
                DataSet ds = ExecSqlCommand(query, out rows); //this method is private to this class

                if (ds == null)
                    return null;

                List<Repositories.Department> list = new List<Repositories.Department>();
                foreach (DataRow row in ds.Tables[0].Rows)
                {
                    list.Add(new Repositories.Department((String)row[DepFN_Symbol], (String)row[DepFN_DepName]));
                    //DepFN_Symbol and the others are just const variables representing the column index
                }

                return list;
            }

    }

public class DepartmentLogic
{
   public DepartmentLogic()
   {
      .....
   }

   public List<Repositories.Department> GetAllDepartments()
   {
      //Here I create an Instance of the DataStorage but using the Department interface
      //so I restrict the access to Department data methods only. It could be a good 
      //idea here to use the factory pattern.

      IDepartmentDS department = (IDepartmentDS) new DataStorage();
      department.Open();

      List<Repositories.Department> departments = department.List();

      department.Close();

      return departments;
   }

}