3

What I am attempting to do, is to be able to use complex objects both for retrieval and for writing back to the database.

For example, I have two classes

[Table("Children")]
public class Child
{
    public int Id { get; set; }
    public int ParentId { get; set; }
    public string Data { get; set; }
}

[Table("Parents")]
public class Parent
{
    public int Id { get; set; }
    public string Data { get; set; }
    public List<Child> Children { get; set; }

    public Parent()
    {
        Children = new List<Child>();
    }
}

I populate the Parent object using the method below

public List<Parent> GetAll()
{
    var parents = new List<Parent>();
    using (SQLiteConnection conn = new SQLiteConnection(sqlConnectionString))
    {
        string sql = $@"
        SELECT * From Parents;
        SELECT * FROM Children;
        ;";

        var results = conn.QueryMultiple(sql);
        parents = results.Read<Parent>().ToList();
        var children = results.Read<Child>();
        foreach (var parent in parents)
        {
            parent.Children = children.Where(a => a.ParentId == parent.Id).ToList();
        }
    }
  return parents;
}

My Question now that I have my populated object, say I want to make changes to Parent including adding/updating/remove values from Parent.Children

This is my first pass at an update method, but I recognize there are issues here, such as making the determination to update or insert based on the child Id being zero or not, as well as this being a bit verbose.

Is there way, and am I missing some functionality of Dapper or Dapper.Contrib that would provide helper methods to make this process easier?

public bool Update(Parent parent)
{
    bool result = true;
    using (SQLiteConnection conn = new SQLiteConnection(sqlConnectionString))
    {
        conn.Open();
        using (var tran = conn.BeginTransaction())
        {
            try
            {
                if (!conn.Update<Parent>(parent))
                {
                    result = false;
                }

                foreach (var element in parent.Children)
                {
                    if (element.Id == default(int))
                    {
                        conn.Insert<Child>(element);
                    }
                    else
                    {
                        if (!conn.Update<Child>(element))
                        {
                            result = false;
                        }
                    }
                }
                tran.Commit();
            }
            catch(Exception ex)
            {
                //logger.Error(ex,"error attempting update");
                tran.Rollback();
                throw;
            }
        }
    }

    return result;
}
Bruce Burge
  • 144
  • 1
  • 15
  • 3
    Maybe you just need to use more "heavy" ORM like Entity Framework where such things are already implemented? – Evk Nov 03 '17 at 17:48
  • Unfortunately, the requirements at hand make entity unlikely, vs2017, sqlite, and EF aren't playing well, and won't likely for quite sometime. – Bruce Burge Nov 03 '17 at 19:59
  • 2
    You mean EF provider for sqlite generates bad queries? And NHibernate? Because "is to be able to use complex objects both for retrieval and for writing back to the database" is all what "heavy" ORMs are about basically. – Evk Nov 03 '17 at 20:05
  • No, basically changes to visual studio 2017 design-time installer, have caused the sqlite team to at least for now, drop support for design-time components. Managing EF without them, internally for us, it was deemed more trouble than it's worth to implement without. [link](https://system.data.sqlite.org/index.html/tktview?name=8292431f51) I will look into NHibernate if I can't get any other answers with Dapper. – Bruce Burge Nov 03 '17 at 21:52
  • As for me, designer support is not required. Theree is code-first, or you can scaffold your database to model classes of you don't like code first. Also EF core (which can be used in full .NET too) supports SQLite (no designer also though, but there is no designer support for EF Core at all out of the box and people still happily use it). – Evk Nov 06 '17 at 09:30
  • I do not see major design issue with what you are doing considering you are using Dapper.Contrib. If you have complex requirements, better consider switching to full ORM as suggested by @Evk. Refer [this](https://stackoverflow.com/a/45460483/5779732) answer that shows how I implemented repository with DapperExtensions. – Amit Joshi Nov 07 '17 at 11:30
  • If sqlite is not a "must have" requirement, Maybe you should consider a NOSQL database like UnQLite or MongoDb? – Helder Sepulveda Nov 07 '17 at 13:36

1 Answers1

3

Sadly, given how poor the response was to this question, and Dapper.Contrib questions in general. I've decided to dump Dapper and switch to an ORM that better suites my needs. Thanks for all those that offered suggestions.

Bruce Burge
  • 144
  • 1
  • 15
  • Excuse me, I'm in your exact situation...what have you pointed to after Dapper? – advapi Jul 18 '18 at 14:12
  • Entity Framework, it too has its challenges and is a bit painful setting up with vs2017 but overall, it has worked for my needs. – Bruce Burge Jul 18 '18 at 17:02