views:

41

answers:

1

Linq to SQL, in the dbml designer (or otherwise)

I have 3 tables:

Orders, Deliveries and EmailTemplates.

Orders have many Deliveries, and Orders and Deliveries have a status (int) field.

EmailTemplates have a status they apply to and a bool IsForDeliveries field.

I have Linq to sql associations for Order->EmailTemplate on order.status == emailTemplate.status, but I want to add a condition on the association such that emailTemplate.IsForDeliveries == false. Is this possible, or do I just have to remember to check this condition whenever I access order.EmailTemplates?

Edit

AssociateWith is problematic because I also need the counterpart Delivery<->EmailTemplate association which only shows templates with e.is_for_delivery == true.

Adding a property to the class is problematic because I'd like this to be translatable to SQL.

+1  A: 

You can use DataLoadOptions.AssociateWith() for this or just create an additional property on the class. Since the Order class is a partial, you could just create a method in a partial beside it adding this:

public IEnumerable<EmailTemplate> DeliveryEmailTemplates {
  get { return EmailTemplates.Where(e => e.IsForDeliveries == false); }
}

or alternatively, when creating the datacontext:

var dc = new DataContext();
var dlo = new DataLoadOptions();
dlo.AssociateWith<EmailTemplates>(o => o.EmailTemplates.Where(e => e.IsForDeliveries == false));
dc.LoadOptions = dlo;

var orders = from o in DB.Orders
             where o.Id == 5
             select o;

foreach(var o in  orders) {
  //o.EmailTemplates will contain only IsForDeliveries==false...
}

If you fetch your DataContext in a static way you can add this every time, for example I add a method in a partial class of the DataContext called .New:

public static DataContext New {
  get { 
        var dc = new DataContext(MyConnectionString);
        var dlo = new DataLoadOptions();
        dlo.AssociateWith<EmailTemplates>(o => o.EmailTemplates.Where(e => e.IsForDeliveries == false));
        dc.LoadOptions = dlo;
        return dc;
      }
 }

Then use:

var DB = DataContext.New;
var orders = from o in DB.Orders
             where o.Id == 5
             select o;
Nick Craver
`!e.IsForDeliveries`
leppie
Hmm... but then if I also need the equivalent Delivery<->EmailTemplate assocation (where e.isForDelivery), I can't use the associatewith (unless I have 2 different context factories). And a method can't be translated to SQL...
Greg
@Greg - Which method can't be translated? There's nothing custom in my post. For the opposite property, you could add 2 properties to the Orders class, just also have the reverse of `DeliveryEmailTemplates` above. If it's an `IQueryable<T>` and not an `EntitySet<T>` already, you can return it as that type, depends on yow you're using it as to what's best.
Nick Craver
DeliveryEmailTemplate. For instance: var x = from o in db.orders where o.DeliveryEmailTemplates.Any() select o;I'm pretty sure that'd give translation error because DeliveryEmailTemplate is a property call.
Greg
...hmm. I might be understanding this wrong...
Greg
@Greg - Can you post the definition of your current `EmailTemplates` property on `Order`?
Nick Craver
@Nick it's automatically generated by creating an association between EmailTemplates and Order in the dbml designer (as if there was a foreign key relation in the db).
Greg
the 'Participating properties' property of the association is 'order.status -> email_template.status'
Greg