1

My application has be entity model as below and use Dapper

public class Goal
{
    public string Text { get; set; }
    public List<SubGoal> SubGoals { get; set; }
}

public class SubGoal
{
    public string Text { get; set; }
    public List<Practise> Practices { get; set; }
    public List<Measure> Measures { get; set; }
}

and has a repository as below

public interface IGoalPlannerRepository
{
    IEnumerable<Goal> FindAll();
    Goal Get(int id);
    void Save(Goal goal);
}

I came across two scenarios as below

  1. While retrieving data (goal entity), it needs to retrieve all the related objects in hierarchy (all subgoals along with practices and measures)
  2. When a goal is saved all the related data need to be inserted and/or updated

Please suggest is there a better way to handle these scenarios other than "looping through" the collections and writing lots and lots of SQL queries.

aravind
  • 535
  • 4
  • 21

1 Answers1

4

The best way to do large batch data updates in SQL using Dapper is with compound queries.

You can retrieve all your objects in one query as a multiple resultset, like this:

CREATE PROCEDURE get_GoalAndAllChildObjects
    @goal_id int
AS
SELECT * FROM goal WHERE goal_id = @goal_id
SELECT * FROM subgoals WHERE goal_id = @goal_id

Then, you write a dapper function that retrieves the objects like this:

using (var multi = connection.QueryMultiple("get_GoalAndAllChildObjects", new {goal_id=m_goal_id})) {
    var goal = multi.Read<Goal>();
    var subgoals = multi.Read<SubGoal>();
}

Next comes updating large data in batches. You do that through table parameter inserts (I wrote an article on this here: http://www.altdevblogaday.com/2012/05/16/sql-server-high-performance-inserts/ ). Basically, you create one table for each type of data you are going to insert, then write a procedure that takes those tables as parameters and write them to the database.

This is super high performance and about as optimized as you can get, plus the code isn't too complex.

However, I need to ask: is there any point to keeping "subgoals" and all the other objects relational? One easy alternative is to create an XML or JSON document that contains your goal and all its child objects serialized into text, and just save that object to the file system. It's unbelievably high performance, very simple, very extensible, and takes very little code. The only downside is that you can't write a SQL statement to browse across all subgoals with a bit of work. Consider it - it might be worth a thought ;)

Ted Spence
  • 2,598
  • 1
  • 21
  • 21
  • Thanks.Your suggestions on "Get" sounds sensible.But update logic is bit complicated. If dapper could not handle it simply, i would opt another ORM. – aravind Aug 21 '12 at 06:18
  • Dapper has lots of ways to do it that aren't quite as intensely high performance. You can easily write traditional Dapper update statements like these: http://stackoverflow.com/questions/5957774/performing-inserts-and-updates-with-dapper – Ted Spence Aug 21 '12 at 15:06
  • @TedSpence "Connection refused" :( Did you move your blog somewhere? – vt100 Sep 30 '15 at 14:00
  • 1
    @vt100 it's here - http://altdevblog.com/2012/05/16/sql-server-high-performance-inserts – aravind Mar 22 '16 at 13:00