Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 从复杂的数据库功能构建复杂对象的好设计模式是什么?_Design Patterns_Data Access Layer - Fatal编程技术网

Design patterns 从复杂的数据库功能构建复杂对象的好设计模式是什么?

Design patterns 从复杂的数据库功能构建复杂对象的好设计模式是什么?,design-patterns,data-access-layer,Design Patterns,Data Access Layer,我有一个复杂的结构,需要使用从数据库读取的数据来构建,我需要知道在哪里放置数据库访问逻辑 我读过关于存储库设计模式的文章,但我的数据库操作不是简单的CRUD,它们不仅仅返回简单的值 我正在连接PostgreSQL并调用函数,这些函数通常以一组游标的形式返回数据 这是我代码的一个非常简化的部分。。。我遗漏了一些细节 class Topic { public string TopicLabel { get; set; } public int TopicCode { get; se

我有一个复杂的结构,需要使用从数据库读取的数据来构建,我需要知道在哪里放置数据库访问逻辑

我读过关于存储库设计模式的文章,但我的数据库操作不是简单的CRUD,它们不仅仅返回简单的值

我正在连接PostgreSQL并调用函数,这些函数通常以一组游标的形式返回数据

这是我代码的一个非常简化的部分。。。我遗漏了一些细节

class Topic
{
    public string TopicLabel { get; set; }

    public int TopicCode { get; set; }

    List<Topic> parentTopics;

    public Topic(int topicCode , string topicLabel)
    {
        ...
    }

}       


class InitialTopic
{
    Topic initialTopic;

    public int TopicCode { get { return initialTopic.TopicCode; } }            
    Dictionary<int, float> similarityValues;

    public InitialTopic( Topic topic)
    {
        initialTopic = topic;
        similarityValues = new Dictionary<int, float>();
    }

}



class TopicsDictionary
{
    Dictionary<int, Topic> topics;

    public TopicsDictionary()
    {
        topics = new Dictionary<int, Topic>();
    }     

    public Topic this[int topicCode]
    {
        get
        {
            Topic t = null;
            if (topics.ContainsKey(topicCode))
            {
                t = topics[topicCode];                    
            }
            else
            {
                t = new Topic(topicCode);
                topics.Add(topicCode, t);
            }
            return t;
        }
    }
}

     .
     .
     .  

public static void GetData(InitialTopic initialTopic)
{

     using (var conn = new NpgsqlConnection(connString))
    {
        conn.Open();
        NpgsqlTransaction tran = conn.BeginTransaction();

        NpgsqlCommand command = new NpgsqlCommand("public.\"GetStuff\"", conn);
        .
        .

        string cursor1, cursor2;
        using (var dr = command.ExecuteReader())
        {
            dr.Read();
            cursor1 = dr[0].ToString();
            dr.Read();
            cursor2 = dr[0].ToString();
        }                   

        using (var resultSet1 = new NpgsqlCommand())
        {
            resultSet1.CommandText = $@"FETCH ALL FROM ""{cursor1}""";
            resultSet1.Connection = conn;

            using (var reader = resultSet1.ExecuteReader())
            {
                // here read values, create Topic objects,
                // add them to TopicsDictionary and link them using parentTopics list 
                // to reflect parent-child relation
            }
        }           

        using (var resultSet2 = new NpgsqlCommand())
        {
            resultSet2.CommandText = $@"FETCH ALL FROM ""{cursor2}""";
            resultSet2.Connection = conn;

            using (var reader = resultSet2.ExecuteReader())
            {
                // here read values and fill similarityValues 
                // dictionary in InitialTopic object
            }
        }

        tran.Commit();
        conn.Close();

    }
}   
课程主题
{
公共字符串TopicLabel{get;set;}
公共int主题代码{get;set;}
列出主题;
公共主题(int-topicCode,string-topicLabel)
{
...
}
}       
类初始主题
{
话题初始话题;
public int-TopicCode{get{return initialTopic.TopicCode;}}
字典相似值;
公共初始主题(主题)
{
initialTopic=主题;
similarityValues=新字典();
}
}
类主题词典
{
词典主题;
公共主题词典()
{
topics=新字典();
}     
公共主题此[int topicCode]
{
得到
{
主题t=null;
if(主题.容器(主题代码))
{
t=主题[主题代码];
}
其他的
{
t=新主题(主题代码);
主题。添加(主题代码,t);
}
返回t;
}
}
}
.
.
.  
公共静态void GetData(InitialTopic InitialTopic)
{
使用(var conn=新的NpgsqlConnection(connString))
{
conn.Open();
NpgsqlTransaction tran=conn.BeginTransaction();
NpgsqlCommand=newnpgsqlcommand(“public.\'GetStuff\”,conn);
.
.
字符串游标1,游标2;
使用(var dr=command.ExecuteReader())
{
里德博士();
cursor1=dr[0]。ToString();
里德博士();
cursor2=dr[0]。ToString();
}                   
使用(var resultSet1=new NpgsqlCommand())
{
resultSet1.CommandText=$@“从“{cursor1}”获取所有内容”;
结果1.连接=连接;
使用(var reader=resultSet1.ExecuteReader())
{
//在这里读取值,创建主题对象,
//将它们添加到TopicsDictionary,并使用parentTopics列表链接它们
//反映亲子关系
}
}           
使用(var resultSet2=new NpgsqlCommand())
{
resultSet2.CommandText=$@“从“{cursor2}”获取所有数据”;
结果2.连接=连接;
使用(var reader=resultSet2.ExecuteReader())
{
//此处读取值并填充相似值
//InitialTopic对象中的字典
}
}
trans.Commit();
康涅狄格州关闭();
}
}   
我是否应该将数据库操作与对象(主题对象及其成员列表和字典)的实际构建分开?我该怎么做?是否有适合这种情况的设计模式

我是否应该将数据库操作与对象(主题对象及其成员列表和字典)的实际构建分开

绝对是的。使用(var reader=时
中的两个代码块非常复杂,因此(1)您的
GetData
方法看起来很难看,(2)您希望对这些代码进行单元测试,以及(3)在切换到另一个数据库系统(例如MySQL)时,您希望重用这些代码

我应该怎么做?有适合这种情况的设计模式吗

只需将
GetData
方法中的两个代码块提取到其他地方。由于您的
InitialTopic
类非常干净,您可以移动到这里。但这取决于您自己

现在唯一的挑战是
InitialTopic
类如何从两个读卡器接收数据。当然,我们将把读卡器传递给
InitialTopic
对象。但是我们不应该让
InitialTopic
类依赖于数据库类(读卡器的类型)

通常,为了解决这个问题,我们采用依赖倒置原则。引入了一个新的接口来抽象读者的操作:

interface MyReader {
    // hasNext() and next() methods, right?
}
我们将让
InitialTopic
类依赖于
MyReader
接口

现在我们编写一个适配器来适应Npgsql读取器(使用(var reader=
)的
中的读取器):

最后,
GetData
方法中的两个代码块变为:

using (var reader = resultSet1.ExecuteReader()) {
    initialTopic.method1(new MyNpgsqlReader(reader));
}
...
using (var reader = resultSet2.ExecuteReader()) {
    initialTopic.method2(new MyNpgsqlReader(reader));
}
我是否应该将数据库操作与对象(主题对象及其成员列表和字典)的实际构建分开

绝对是的。您的
using(var reader=
中的两个代码块非常复杂,以至于(1)您的
GetData
方法看起来很难看,(2)您想对这些代码进行单元测试,(3)您想在切换到另一个数据库系统(例如MySQL)时重用这些代码

我应该怎么做?有适合这种情况的设计模式吗

只需将
GetData
方法中的两个代码块提取到其他地方。由于您的
InitialTopic
类非常干净,您可以移动到这里。但这取决于您自己

现在唯一的挑战是
InitialTopic
类如何从两个读卡器接收数据。当然,我们将把读卡器传递给
InitialTopic
对象。但是我们不应该让
InitialTopic
类依赖于数据库类(读卡器的类型)

通常,为了解决这个问题,我们采用依赖倒置原则。引入了一个新的接口来抽象读者的操作:

interface MyReader {
    // hasNext() and next() methods, right?
}
我们将让
InitialTopic
类依赖于