Associations with Payloads - part Deux

Okay so the 'cat is out of the bag' you CAN do associations with Payloads... Sort of.

Now for an explanation of what I meant by 'Sort of'.

Let's dream a little and imagine how it might work in an ideal world. Imagine something like this:

Product p = ...;
Order o = ...;

o.Products.Add(p);

Under the hood we would like the EF to create for us a new OrderLine, problem is we have no way of telling the EF what payload should be, i.e. what the the Quantity, UnitPrice and Discount's for this OrderLine should be. So either we have to have (1) default values, (2) nullable values or we have to have a way of (3) specifying the information.

Let's look at our options in turn:

  1. Default values is pretty inflexible. How do you change the Quantity to 2 from a default of 1? Create two relationships? Yuck! Create the relationship with the wrong value and then load it as an entity to modify it? Yuck!
  2. Nullable, well that defeats the purpose of the underlying table. There is a quantity for a reason, an order means nothing without one!
  3. Setting the values?

Option (3) it seems is the only realistic option, but even that upon investigation has issues.

How do you provide the values? Using events?

ctx.ProductOrders.OnAdd += new ProductOrdersEventHandler(...);

Two problems: this requires a whole new set of capabilities the EF currently doesn't have, classes for associations, event handlers and the ability to hook into the association change pipeline, but perhaps more damningly... it is kind of like default values anyway, because unless you wire and unwire the handler before and after each attempt to alter an association, the same shaped OrderLine would be created each time.

Okay, so the main problem is we need more granularity (or interaction-ality), how about a lambda expression then?

o.Products.Add(p, (ProductOrdersEventArgs args) =>
Product product = args.Association.Right;
Order order = args.Association.Left; //Association would be a generic class OrderLine line = new OrderLine();
line.ID = Guid.NewGuid();
line.Product = product;
line.Order = order;
line.Quantity = 25;
line.UnitPrice = 1.54;
line.Discount = .125;

    //Add the key line -> something to tell the EF OrderLine will do the association args.Association = line; //Or something equally as tricky... );

Well, first off this is a lot of work, for both users and the EF team, secondly it is vaguely incomprehensible for lots of devs, but worse yet, if we supported something like this it is a whole heap more complication than something as simple as just managing the association using Entities the normal way:

     OrderLine line = new OrderLine();
line.ID = Guid.NewGuid();
line.Product = product;
line.Order = order;
line.Quantity = 25;
line.UnitPrice = 1.54;
line.Discount = .125;
ctx.AddToOrderLines(line);

But that extra complexity buys you nothing.

Perhaps then... that is the best we can actually hope for?

Perhaps what we want then is a READONLY association. One that you can use for queries and object materialization etc, but one you can't modify directly.

If you want to modify the association then you have to modify it off to the side, using standard EF code.

Best of all this is something you can do today, sort of, with a little jiggery pokery ;)

This is what I'll show you how to do in my next post.