Home > C#, Magiq > Magiq: Mass inserts and deletes with linq-to-sql

Magiq: Mass inserts and deletes with linq-to-sql

In my previous post I talked about how the update feature was implemented in Magiq. Now it’s insert and delete’s time :).
I have to say, the Delete feature was pretty simple. Since we have the where clause, it’s just trivial create a sentence DELETE <<TableName>> FROM <<Where clause>>. And as for the updates we needed the “source” repository (the DataContext), it was just simple.
:)
I have to say that implementing the Insert feature wasn’t that simple.
My first approach was to create a single select expression with the “new ClassToInsert{ }” stuff, so I would be able to get all the sql values with one single call. When I finally implemented it, I realize that linq-to-sql doesn’t like to create new instances of mapped classes. It makes sense from the linq-to-sql point of view, but not for Magiq. So I implemented it the same way that for updates, one call per property.
One single sql or multiple sql, both approaches requires to create the select expression. Since what I have was just a MemberInitExpression , I had to find a way to convert it to a Select expression.
From this:

x => new Product{
                  Name = "Test",
                  Price = x.Price *1.8
                }

To this:

x => "Test"
x => x.Price *1.8

My first disovery was when you assign constants to a select, linq-to-sql doesn’t add them to the query and use the actual values when hydrating the objects. So, if the expression was some kind of constant (ConstantExpression, ConvertExpression of a ConstantExpression, MemeberAccessExpression of a ConstantExpression) I should compile the expression and create a Lamda with a ConstantExpression as body:

var lambda = Expression.Lambda(expression, Expression.Parameter(typeof(F), "x"));
var value = lambda.Compile().DynamicInvoke(new object[] {null});

If the expression is not a constant, then:

var expression = expression.Type.IsValueType
                      ? Expression.Convert(baseExpression, typeof (object))
                      : baseExpression;
var lambda = Expression.Lambda<Func<F, object>>(expression, baseExpression.GetParameter());

I have to convert the value types to object because the signature of the delegate I’m using.

Finally, As MemberInitExpression has collection of assignments and each of them are expressions, I could do:

var newExpression = (MemberInitExpression) insert.NewExpression.Body;
foreach (MemberAssignment assignment in newExpression.Bindings) {
     if (IsConstant(assignment.Expression))
           var lambda = ...;
     else
           var lambda = ...;
}

I was very happy when I made this expressions work 🙂

Advertisements
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: