【问题标题】:Creating objects vs. SELECTing directly from database创建对象与直接从数据库中选择
【发布时间】:2012-10-02 20:27:29
【问题描述】:

我目前正在开展一个集成项目,以连接两个不同的系统。
我的计划是设置一个 HTTP-API 以允许系统 A 通过 HTTP-POST 向系统 B 发出命令。
这些命令将用于向 SQL 服务器数据库发出 CRUD 指令,以检索和更新会员卡数据(例如“创建会员”、“更新会员”等),然后将数据以 XML 格式返回给系统 A。我知道 n 层设计要求我应该有一个具有多个属性的 MembershipCard 类:

public class MembershipCard
{
    private string number;
    private decimal points;

    public string Number
    {
        get { return number; }
        set { number = value; }
    }

    public decimal Points
    {
        get { return points; }
        set { points = value; }
    }

以及调用 DAL 的几种方法:

    public string GetPoints(string cardnumber) 
    {
        return MembershipCardDB.BalanceRequest(cardnumber);
    }

但是,我在将这种方法证明为静态 DAL 类时遇到了一些困难,MembershipCardDB 似乎执行了我需要的所有工作(见下文):

    public static string BalanceRequest(string cardNumber)
    {
        string response = string.Empty;
        string sqlselect = 
            "SELECT Balance                         " +
            "FROM tbl_MemberShipCard                " +
            "WHERE Card_No = @cardNumber                 " +
            "FOR XML PATH ('Card'), ROOT('CardBalance')";

        using (SqlConnection connect = new SqlConnection("Data Source=TEST\\TEST;Initial Catalog=TEST;User Id=sa;Password=TEST"))
        {
            connect.Open();
            using (SqlCommand command = new SqlCommand(sqlselect))
            {
                command.Parameters.AddWithValue("@cardNumber", cardNumber);
                response = (string)command.ExecuteScalar();
            }
        }
        return response;
    }

通过简单地删除 MembershipCard 类并从数据库中提取数据并将其格式化为 XML 有什么我忽略的吗?

【问题讨论】:

  • 如果这是整个应用程序中唯一的方法,那么在我的书中删除 MembershipCard 类是可以接受的。 n 层设计结构用于重用和可读性。但我在将 Console.ReadLine 放入打开的 SQL Server 连接时确实存在问题。 SQL Server 连接有限且成本高昂,因此应尽快打开和关闭它们。
  • 顺便问一下,你为什么要这样做?我可以建议使用实体框架来做到这一点吗?在当今时代,没有理由像这样手动实施“CRUD 存储系统”。
  • @GeneS 很抱歉,我刚刚将 Console.ReadLine() 用于测试。我已更新问题以更正它。

标签: c# sql-server-2008 api http-post n-tier-architecture


【解决方案1】:

重点是您应该能够独立于任何数据库接口或 xml 格式编写程序逻辑。将所有数据库内容放入加载和创建对象的单独类中。对对象做任何你想做的事情。最后将对象存储回数据库或 xml。但是,如果您的代码只是关于导入和导出数据,则可以删除额外的类。

顺便说一句,您可以通过使用自动实现的属性来简化MembershipCard 类:

public class MembershipCard
{
    public string Number { get; set; }
    public decimal Points { get; set; }
}

我经常有一个静态的DB

public static class DB
{
    public static string GetBalanceRequest(string cardNumber)
    {
        ...
    }

    public static MembershipCard LoadMembershipCard(string cardNumber)
    {
        ...
    }

    public static List<MembershipCard> LoadMembershipCards()
    {
        ...
    }

    public static void SaveMembershipCard(MembershipCard membershipCard)
    {
        ...
    }
}

你的MembershipCard 类可以有一个方法

    public string BalanceRequest()
    {
        return DB.GetBalanceRequest(this.Number);
    }

像这样,您可以将数据库操作和其他应用程序逻辑分开。

【讨论】:

    【解决方案2】:

    如果您专门公开 CRUD 操作,REST 接口可能是要走的路(请参阅Web API)。有了这条路线,我相信你有理由直接使用你的数据库类。这并没有真正违反 N 层方法 - Web 服务实际上充当数据层的接口。

    您甚至可以更进一步,使用当前版本中的 OData 支持公开对您的服务的延迟执行查询。

    主要问题是 Web API 仍处于测试阶段,并且会定期更改。例如,发布预览版中几乎没有 OData 支持。它在夜间构建中要先进得多。

    【讨论】:

      【解决方案3】:

      建筑是一件有趣的事情。在选择范例之前,最好先准确评估您想要完成的目标。

      有时 n 层设计可以在以后节省您的时间,但有时您今天必须编写的额外代码量是不值得的。听你这么说,你好像已经进入了后者阵营。

      所以,回到我的第一句话,您应该问自己:您预见到需要将数据格式化 (XML) 与检索 (SQL 查询) 分开吗?

      在某些情况下您可能会这样做。例如,XML 非常冗长,并且包含许多您以后可能不需要的额外的非信息性数据。通过将自己与 SQL Server 发出 XML 的方式联系起来,如果您决定使用 JSON,您将面临重写。

      再进一步,XML 甚至 JSON 都适用于有限数量的数据,例如一次传输几条记录,但如果您开始一次传输数百或数千条数据,那么数据量很容易达到您所需要的点只是想通过网络发送类似于 CSV 文件的内容。同样,您将面临重写。

      但是,如果您在构建它时只需插入一个新的提供程序来处理各种格式要求,那么您将编写新代码而不是替换可能大量的旧代码补丁......而且它也很容易支持如果格式与检索不紧密耦合,则同时使用多种格式(XML、Json、CSV、Excel 等)。

      扮演魔鬼的拥护者,如果我们谈论的是一个小型系统,这可能并不重要,因为由于格式更改而重写代码所花费的时间可能是微不足道的,此时我不会花时间构建一个 n层模型。

      希望对您有所帮助,最终我认为我们无法告诉您该走哪条路。

      【讨论】:

        【解决方案4】:

        n 层设计要求我应该有一个具有多个属性的 MembershipCard 类

        我不确定这是否准确。我认为 n 层设计规定每一层只依赖于它下面的层。并且每一层不需要仅仅依赖于它下面的层直接 - 你可以跳过关卡。因此,您的 Web 服务接口可以跳过域层并直接进入存储库。尽管即便如此,最好在中间添加另一个层,例如“应用程序”,它为您提供了添加额外非数据访问逻辑的空间,而不是让它泄漏到您的 UI/Web 服务中。

        您的数据库访问类中的“Console.ReadLine”将 UI 与存储库混合在一起,因此这显然不好。另外,使用静态方法使得编写单元测试变得困难,所以这也不好。

        查看... Eric Evans 的领域驱动设计。

        【讨论】:

          猜你喜欢
          • 2021-02-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-04-26
          • 2011-03-16
          • 1970-01-01
          • 2020-09-12
          • 2012-07-15
          相关资源
          最近更新 更多