1

What is the best practice for the following scenario:

I have a LINQ to SQL expression where in its projection I want to call a private method. I understand that my method cannot be translated into SQL, but I do need the logic. Changing the property after getting the query result is not possible since you cannot change a projected property (it is read only).

10x

var projectedOrders = from order in orders
    select new
    {
        orderId = order.Id,
        orderName = order.FriendlyName,
        OrderDate = order.OrderDate,
        CustomerName = helper.GetUserNameByUserId(order.UserId)
    };
Tim S. Van Haren
  • 8,861
  • 2
  • 30
  • 34
MichaelLo
  • 1,289
  • 1
  • 14
  • 26
  • Changing the property on the existing item is not possible, but you could `select` out a new collection after getting the result. – crthompson Apr 17 '14 at 15:41
  • If the method is simple, how about using dynamic LINQ? See end of [this article](http://weblogs.asp.net/davidfowler/archive/2010/08/19/dynamic-linq-part-2-evolution.aspx) for example and explanation – voidengine Apr 17 '14 at 15:51
  • @paqogomez check this out: http://stackoverflow.com/questions/1089406/why-are-the-properties-of-anonymous-types-in-c-sharp-read-only – MichaelLo Apr 17 '14 at 15:54
  • Yes, that is correct. I was suggesting what all these answers are suggesting, you have to do it twice. Once to get the result, then create a new array that calculates your value. Exactly as @Jaimec suggests. – crthompson Apr 17 '14 at 16:01

2 Answers2

4

You'll have to do it in 2 steps

  • query the raw data from the database, and materialize it
  • project onwards using your logic

var projectedOrders = (from order in orders
                          select new
                          {
                              orderId = order.Id,
                              orderName = order.FriendlyName,
                              OrderDate = order.OrderDate,
                              UserId= order.UserId
                          })
                       .ToArray()
                       .Select(o =>
                           new{
                              o.orderId,
                              o.orderName,
                              o.OrderDate,
                              CustomerName = helper.GetUserNameByUserId(o.UserId)

                           });
Jamiec
  • 133,658
  • 13
  • 134
  • 193
1

You can store the UserId temporarily into a property and set CustomerNames to null, then use a loop after your query and change the value of CustomerNames:

var projectedOrders = (from order in orders
                      select new
                      {
                              orderId = order.Id,
                              orderName = order.FriendlyName,
                              OrderDate = order.OrderDate,
                              UserId = order.UserId,
                              CustomerName = null
                       }).ToList();

foreach(var order in projectedOrders)
        order.CustomerName = helper.GetUserNameByUserId(order.UserId);
Selman Genç
  • 100,147
  • 13
  • 119
  • 184