vendredi 17 mai 2019

What is a good design pattern to build complex objects from complex database function?

I have a complex structure that needs to be built using data read from database, and I need to know where to place my database access logic.

I read about Repository design pattern, but my database operations are not simple CRUD, and they are not just returning simple values.

I am connecting to PostgreSQL and calling functions that often return data as a set of cursors.

Here is a very simplified part of my code... I have omitted some details

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();

    }
}   

Should I separate database operation from the actual building of objects (topic objects and their member lists and dictionaries) ? How should I do that? Is there an appropriate design pattern for such case?

Aucun commentaire:

Enregistrer un commentaire