1

我正在为我的应用程序的主要数据层使用 MS Enterprise Library 5.0(数据访问块)。

虽然我了解 OO 的基础知识(是的,我需要不断学习 - 不断学习!),但我正在努力了解在哪里/为什么/如何使用好的设计,即不要不必要地重复代码等,而且仍然试图保持代码简单易读,当然还有调试。

所以首先,我有以下类和默认/示例方法:(ps:db/proc 的返回值是 XML)

public class ajaxget
{
    public enum outputType : int { JSON = 0, XML = 1 }

    public static string getMemberContacts(string sStartsWith, string sEndswith, outputType eOT)
    {
        //  Get the associated members based upon the criteria
        Database db = DatabaseFactory.CreateDatabase("MyDatabase");
        DbCommand cmd = db.GetStoredProcCommand("get_memberContactsXML");
        db.AddInParameter(cmd, "@memberID", DbType.Int64, Convert.ToInt64(sID));
        db.AddInParameter(cmd, "@startsWith1", DbType.String, sStartsWith);
        db.AddInParameter(cmd, "@startsWith2", DbType.String, sEndswith);
        IDataReader dr = db.ExecuteReader(cmd);
        StringBuilder sb = new StringBuilder();
        while (dr.Read())
        {
            sb.Append(dr.GetValue(0));
        }

        //  Clean up
        dr.Close();
        dr.Dispose();
        cmd.Dispose();

        //  What format to return?
        if (eOT == outputType.XML)
        {
            return sb.ToString();
        }
        if (eOT == outputType.JSON)
        {
            XmlDocument xdoc = new XmlDocument();
            xdoc.LoadXml(sb.ToString());
            return JsonConvert.SerializeXmlNode(xdoc);
        }
    }
}

所以..到目前为止非常基本。我只是想在这里建立一个模板,说明我应该如何继续说更多“getMemberContacts”方法。即我应该创建一个通用的“get”方法,它是一个虚拟方法,并覆盖参数?我知道这听起来很治愈,确实如此!我猜是学习的一部分。

所以总而言之,我当然试图重用“get”方法,其中 params/proc 名称明显不同,但是实际返回值(在这种情况下为 XML,因此连接返回的 while/append 部分XML 块)需要相同,即返回可以保留为 XML,或者如果提供,可以返回 JSON。

我意识到这是非常基本的东西/概念,但任何指针/想法都将不胜感激!

大卫。

- - 编辑 - -

只是为了展示 SQL 2008 XML 部分,因为我对关于不直接从 SQL 返回 XML 的评论感到好奇——我再次明白,获取原始数据以便以不同方式使用它是一件好事,但在我的情况下,所有我的前端框架使用 XML 或 JSON(顺便说一下,JS 框架是 www.dhtmlx.com,它非常棒)。

所以 SQL 2008 的过程是:

CREATE PROCEDURE [dbo].[get_messagesForMemberXMLByID]
    @memberID as bigint=null,
    @days as int=-7
AS
BEGIN
    SET NOCOUNT ON;

    /* Setup the starting point (in the past) from when we wish to select the messages */
    Declare @startDate datetime
    set @startDate = DateAdd(d,@days, getdate())

    SELECT inboxID as "@id", convert(varchar(12),messageCreated,13) as messageCreated, convert(varchar(8), messageCreated,108) as messageCreatedTime, subject,message, messageOpened, messageFrom, messageFromID
    FROM bizzbox
    WHERE memberID = @memberID
    AND convert(char(8), messageCreated, 112) BETWEEN convert(char(8), @startDate,112) AND convert(char(8), getdate(), 112)
    ORDER BY messageCreated desc
    FOR XML PATH('row'), ROOT('rows')
END

输出拉回为:

<rows>
  <row id="1">
    <messageCreated>31 Oct 2010 </messageCreated>
    <messageCreatedTime>21:27:32</messageCreatedTime>
    <subject>Testing 123</subject>
    <message>Wibble Bibble!</message>
    <messageFrom>David</messageFrom>
    <messageFromID>7</messageFromID>
  </row>
</rows>

..这正是我需要为我的前端格式化的数据的方式。

我可以看到为什么不使用这种方法的原因——例如,如果我使用另一个框架或需要直接数据表中的数据怎么办..我想我可以有一个参数变量以 XML 或直接表格形式输出..或者我什至敢说两个 procs .. 但同样,有兴趣听到任何方式的评论...

再次感谢所有输入 - 真的非常感谢。

4

2 回答 2

1

这是一个相当复杂的问题,因此对此的答案将是多种多样的。首先,由于您处于学习阶段...

  1. 对于方法、参数、变量等的名称,坚持 C# 约定。除非你真的必须,否则不要使用匈牙利符号(在某些极端情况下可以使用匈牙利符号,但不能使用它们。
  2. 使用 Enum 时,请使用 Switch 语句而不是 if-else。
  3. 也属于上面的命名约定,但我想我会单独强调这一点 - 枚举值应该是 .Xml 和 .Json 而不是 XML 和 JSON。

我有一些问题: 1. 你为什么使用 Xml?2. 为什么您保存成员联系人的数据库表没有表示成员联系人属性的“字段”?

要回答您关于重新使用“get”方法的问题之一......我不会为每个 get 使用单独的方法,因为参数的类型和数量总是会改变。在这些方法中,您可能具有所有“get”方法都可以使用的私有方法的通用功能,但每个方法本身应该是独立的。这是因为您应该查看具有公共(或内部)API 的数据访问类。这就是当你查看这个类的公共方法时,你应该很好地了解这个类可以做什么以及它需要什么参数才能做到这一点。拥有一种通用方法不仅会让您费尽心思尝试将方形钉插入圆孔,而且通过查看您的公共方法,您将不知道它提供了什么功能。

您的方法 GetMemberContacts 应具有以下签名

public static List<MemberContact> GetMemberContacts(int memberId)

因此,为了获取特定成员的联系人,该成员的 Id 应作为参数传入。该方法很可能会返回 Membercontact 列表或 DataTabl/DataSet。

如果您需要 XML,那么业务层可以获取该数据并将其转换为 xml。如果需要,可以使用相同的 List 并将其转换为 Json。让业务层决定或更好,让它有 3 种方法,以 3 种不同的方式(A List、Json、Xml)返回特定成员的联系人。

不确定代码中的 sStartWith 和 sEndWith 是什么。这意味着,您需要一个更好的方法名称和更好的参数名称来正确指示意图。

于 2010-11-15T03:22:27.667 回答
1

首先,您需要使用using构造而不是手动处理事物。您可以在任何实现 IDisposable 的东西上使用using构造:

StringBuilder sb = new StringBuilder(); 

using(DbCommand cmd = db.GetStoredProcCommand("get_memberContactsXML"))
{
    db.AddInParameter(cmd, "@memberID", DbType.Int64, Convert.ToInt64(sID)); 
    db.AddInParameter(cmd, "@startsWith1", DbType.String, sStartsWith); 
    db.AddInParameter(cmd, "@startsWith2", DbType.String, sEndswith); 
    using(IDataReader dr = db.ExecuteReader(cmd))
    { 
        while (dr.Read()) 
        { 
            sb.Append(dr.GetValue(0)); 
        } 
    }
}

using 语句的优点(除了简洁、易读且通常很棒)是,即使发生异常,它也会确保资源被处理掉。在您的示例中,调用 db.ExecuteReader(cmd) 的异常会导致命令无法处理。

Shiv Kumar 也提出了一些非常好的观点。我会做这样的事情:

public abstract class DataAccessLayerBase
{
    protected string GetXml(string storedProcedureName, OutputType outputType, params Tuple<string,DBType,object>[] parameters)
    {
        StringBuilder sb = new StringBuilder();

        //  Get the associated members based upon the criteria  
        Database db = DatabaseFactory.CreateDatabase("MyDatabase");  

        using(DbCommand cmd = db.GetStoredProcCommand(storedProcedureName))
        {
            foreach(var parameter in parameters)
            {
                db.AddInParameter(cmd, parameter.Item1, parameter.Item2, parameter.Item3);
            }

            using(IDataReader dr = db.ExecuteReader(cmd))
            {
                while (dr.Read())  
                {  
                    sb.Append(dr.GetValue(0));  
                }  
            }      

            switch(outputType)
            {
                case OutputType.Xml:
                    return sb.ToString();  
                case OutputType.Json:
                    XmlDocument xdoc = new XmlDocument();  
                    xdoc.LoadXml(sb.ToString());  
                    return JsonConvert.SerializeXmlNode(xdoc);  
                default:
                    throw new NotSupportedException(); // Some sort of error.
            }
        }
    } 
}

然后只需为每个功能区域创建一个子类:

public class MemberContactsDal : DataAccessLayerBase
{
    public string GetMemberContacts(long memberID, string startsWith, string endsWith, OutputType outputType)
    {
        // Call the method in the base class to handle all of the parsing.
        return GetXml(
            "get_memberContactsXML", 
            outputType, 
            new Tuple("@memberID", DBType.Int64, memberID ), 
            new Tuple("@startsWith1", DBType.String, startsWith), 
            new Tuple("@startsWith2", DBType.String, endsWith)
        );
    }
}

如果存储过程返回 XML,听起来确实有点可疑。

我希望我的例子有所帮助。我没有尝试编译它,但它应该是正确的。

于 2010-11-15T03:53:30.617 回答