Tuesday, February 27, 2018

I saw Spencer Schneidenbach speak on Expressions in C# at the St. Louis .NET User Group last night.

Alright, Func<string, string> and Expression<Func<string, string>> look similar but the Func is for a lambda that actual does something while the Expression is for a describing the lambda and this similarity yet distinction may be thought of as homoiconicity! Already lost? Yeah, me too. Like a lot of tech talks this one was a fire hose. You shouldn't feel embarrassed when you emerge from a tech talk and didn't really get it. A tech talk teases you with ideas that you may go Google on your own. You're not supposed to come out of a tech talk as if it were a college class or nothing. One thing Julie Lerman said at a wrap up panel at the end of the AngularMix that I keep thinking of is that you "probably are getting some of it" even if you feel lost. Anyways, I did get some things from this talk. Spencer tried to demystify the magic, but I came away understanding that magic allows for one to write Expressions in C# which may translate to T-SQL. For example this familiar bit of Entity Framework logic...

var products = db.Products
   .Where(p => p.Name = "eggs")
   .OrderByDescending(p => p.Price);

 
 

This ends up making some T-SQL like so, right?

SELECT * FROM Products
WHERE Name = 'eggs'
ORDER BY Price DESC

 
 

The Where clause in C# is an Expression tree! We can see in the slide in the photo here how it makes sense of eggs and gets them into SQL as a WHERE condition in T-SQL. w00t! That could be more interesting yet. What if we want to use AutoMapper with Entity Framework to slurp into a light DTO collection in C# two columns out of table with two hundred columns for some nimble operation in spite of the fat source? There are some challenges with that. Let's assume this DTO:

public class ItemDetail
{
   public int Id { get; set; }
   public string Name { get; set; }
}

 
 

Alright, this...

var itemDetails = Mapper.Map<ItemDetailModel[]>(db.ItemDetails);

 
 

Gives:

SELECT * FROM ItemDetails

 
 

...which is not cool. No select star please! The better way to go is this:

var itemDetails = db.ItemDetails.ProjectTo<ItemDetailModel>();

 
 

Yielding...

SELECT ID, Name FROM ItemDetails

 
 

Now the two examples so far happen under the hood without you having to know anything about Expressions. When would you want to write an Expression yourself? Alright, let's say you are doing some ETL integration work, maybe for an acquired company or something, and want to map the SalesForceCustomer records like this...

public class SalesForceCustomer
{
   public string CustomerName { get; set; }
   public DateTime? CreateDate { get; set; }
}

 
 

...to QuickbooksCustomer records like so...

public class QuickbooksCustomer
{
   public string Name { get; set; }
   public DateTime? OpenDate { get; set; }
}

 
 

You may do so like this:

public class SfCustomerToQbCustomer
{
   public SfCustomerToQbCustomer()
   {
      SourceField(sfc => sfc.CustomerName.Trim())
         .IsEqualTo(qbc => qbc.Name);
      SourceField(stc => stc.CreateDate ?? DateTime.Now)
         .IsEqualTo(qbc => qbc.OpenDate);
   }
}

 
 

SQL tricks like LTRIM(RTRIM(Name)) and ISNULL(CreateDate, GETDATE()) will be accommodated! Spencer also talked about how Expressions may be faster than reflection as suggested here and here (getting into the Expression API some) and beyond the Spencer Schneidenbach talk there was a lightning talk by a Derek Scheller on imposture syndrome wherein he dropped the term "boyscouting" which he described as the nitpicky need to clean up random things one ecounters which can lead to this problem.

No comments:

Post a Comment