Search code examples
c#insertforeign-keyssimple.data

Simple.Data insert complex object


It's my first day with Simple.Data. I am migrating my project from pure ADO .NET.

I have an Order table with columns:

Id
CreationDate
CustomerId  -> FK to Customer table

And an Order class in my project:

int Id
DateTime CreationDate    
Customer Customer

To insert new Order to database I am doing:

var newOrder=...
_db.Orders.Insert(new {
                       CreationDate=newOrder.CreationDate,
                       CustomerId = newOrder.Customer.Id
                      }
                 );

Is it possible to do it simplier? Simplier for me means without creating new anonymous object and copying each property value. I know that Simple.Data provide Implicit Casting with Insert but when I am trying this:

var newOrder=...
_db.Orders.Insert(newOrder);

I am getting an Exception "CustomerId cannot be NULL" from my SqlServer.


Solution

  • I don't think it's possible at the moment, but Mark is looking into "allowing object graphs to be saved with a single call, if that’s actually possible" for v2 (see his blog post: http://blog.markrendle.net/2013/09/18/simple-data-2-0/, especially the "Better WithStuff" paragraph).

    However you could avoid copying each property value by converting your "newOrder" object to dynamic and simply "adding" the "CustomerId" value to it, like this:

    var d = newOrder.ToDynamic();
    d.CustomerId = newOrder.Customer.Id;
    _db.Orders.Insert(d);
    

    where "ToDynamic()" is a simple extension method:

    public static dynamic ToDynamic(this object @this)
    {
        IDictionary<string, object> expando = new ExpandoObject();
    
        foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(@this.GetType()))
        {
            expando.Add(property.Name, property.GetValue(@this));
        }
    
        return expando as ExpandoObject;
    }
    

    Simple.Data will ignore the original "Customer" property during insert, as the underlying table does not have column for this.