Eliminating Cylclomatic Complexity by replacing switch/case with a method or a Dictionary<TKey, func<>>

Cyclomatic Complexity is a measurement of how many paths your code could traverse. Switch/case statements are often immediate Cyclomatic Complexity concerns.

Cyclomatic Complexity Example

Imagine the following code:

public void Foo(int val)
{
    switch (val)
    {
        case 0:
            // ... code here
            break;
        case 1:
            // ... code here
            break;
        case 2:
            // ... code here
            break;
        case 3:
            // ... code here
            break;
        case 4:
            // ... code here
            break;
        case 5:
            // ... code here
            break;
        case 6:
            // ... code here
            break;
        case 7:
            // ... code here
            break;
    }
}

In the above code, there are 8 paths. The Cyclomatic Complexity is not small. This makes unit tests difficult. It is complexity that is unnecessary. Unnecessary complexity leads to bugs.

Replacing a switch/case statement

Almost invariably, the switch/case statement can be replaced in a way that removes the cyclomatic complexity.

Note: While this article is about C#, it might be helpful to note that Python didn’t even implement a switch/case statement.

There are three replacements methods I am going to dicuss here.

  1. Replace with a Method
  2. Replace with a Method and a dictionary provided parameter.
  3. Replace with Dictionary<TKey, Func<>>

To know which one to choose, you have analyze the code. In the above example, I left out the code. I just put a place holder for it.

// ... code here

After analyzing the code, you should be able to pick one of the following:

Method

So you should use a method if you can.

Example 1
Imagine the following snippet. This is an easy one. You should pick out the replacement without having to be told what it is.

public void Foo(int val)
{
    switch (val)
    {
        case 0:
            Bar.Do(0);
            break;
        case 1:
            Bar.Do(1);
            break;
        case 2:
            Bar.Do(2);
            break;
        case 3:
            Bar.Do(3);
            break;
        // , ... , 
        case 7:
            Bar.Do(7);
            break;
    }
}

As you can see here, each method is easily following a pattern. We can replace the switch statement with a single method call.

public void Foo(int val)
{
    Bar.Do(val);
}

Look, that one was obvious and it was intended to be obvious. It isn’t always going to be obvious.

Example 2
Imagine the following snippet. This is also an easy one, but not quite as easy as above. Hopefully, you pick out the replacement without having to be told what it is.

public void Foo(int val)
{
    switch (val)
    {
        case 0:
            Bar.Do0();
            break;
        case 1:
            Bar.Do1();
            break;
        case 2:
            Bar.Do2();
            break;
        case 3:
            Bar.Do3();
            break;
        // , ... , 
        case 7:
            Bar.Do7();
            break;
    }
}

Notice there is a pattern. We know the method name to call on Bar because we can see the pattern: “Do” + val

We could easily use reflection to eliminate cyclomatic complexity here.

Note: While reflection is often deemed slow and a cause of performance issues, in practice, unless looping through large data sets, any performance loss from reflection is not measurable.

public void Foo(int val)
{
    typeof(Bar).GetMethod("Do" + val).Invoke();
}

We traded Cyclomatic Complexity for Reflection and a possible, but unlikely performance issue. If this code is used in a loop for millions of instances in a data set, you might not want to do this.

Method and a dictionary provided parameter

Example 1
Imagine the code is more like this, in which different case statements call different overloaded values.

public void Foo(int val, ObjA a)
{
    switch (val)
    {
        case 0:
            Bar.Do(a, 3);
            break;
        case 1:
            Bar.Do(a, 7);
            break;
        case 2:
            Bar.Do(a, 5);
            break;
        case 3:
            Bar.Do(a, 100);
            break;
        case 4:
            Bar.Do(a, 9);
            break;
        case 5:
            Bar.Do(a, 12);
            break;
        case 6:
            Bar.Do(a, -1);
            break;
        case 7:
            Bar.Do(a, int.MaxValue);
            break;
    }
}

So every case statement is doing something different. However, notice that what it does differently is a static int. We can create a static parameter dictionary of type Dictionaryint, int>.

internal Dictionary<int, int> ParamMap = new Dictionary<int, int> { {0,3}, {1,7}, {2,5}, {3,100}, {4,9}, {5,12}, {6,-1}, {7, int.MaxValue } };

public void Foo(int val, ObjA a)
{
    Bar.Do(a, ParamMap[val]);
}

This uses a static, prebuilt dictionary that completely eliminates Cyclomatic Complexity.

Notice all the Cyclomatic Complexity is gone. This code never branches. There is very little left to test.

Example 2
Imagine the code is more like this, in which different case statements call different overloaded values.

public void Foo(int val, ObjA a, ObjB b, ObjC c)
{
    switch (val)
    {
        case 0:
            Bar.Do(a);
            break;
        case 1:
            Bar.Do(b);
            break;
        case 2:
            Bar.Do(c);
            break;
        case 3:
            Bar.Do(a, c);
            break;
        case 4:
            Bar.Do(b, c);
            break;
        case 5:
            Bar.Do(b, c, a);
            break;
        case 6:
            Bar.Do(b, c, a * .01);
            break;
        case 7:
            Bar.Do(a, b, c);
            break;
    }
}

This looks harder doesn’t it. The Cyclomatic Complexity can still be simplified. How are we going to do it?

Well, one option is to use a Dictionary<int, object[]>.

public void Foo(int val, ObjA a, ObjB b, ObjC c)
{
    var Dictionary<int, object[]> paramMap = new Dictionary<int, object[]>();
    paramMap.Add(0, new []{ a });
    paramMap.Add(1, new []{ b });
    paramMap.Add(2, new []{ c });
    paramMap.Add(3, new []{ a, c });
    paramMap.Add(4, new []{ b, c });
    paramMap.Add(5, new []{ b, c, a });
    paramMap.Add(6, new []{ b, c, a * .01 });
    paramMap.Add(7, new []{ a, b, c });
    typeof(Bar).GetMethod("Do").Invoke(paramMap[val]); // Reflection allows for passing in a dynamically sized list of parameters.
}

The solution is almost exactly the same as above. The differences are:

  1. The dictionary is dynamic, based on the passed in parameters, so we have to build it dynamically.
  2. The parameters are dynamic so we call the method with reflection to allow for dynamic parameters.

The dictionary still completely eliminates Cyclomatic Complexity. Notice all the Cyclomatic Complexity is gone. This code never branches. There is very little to test.

There is the overhead of creating a Dictionary and the overhead of reflection, but again, unless you plan to use this for looping through large data sets, the performance difference is negligible.

Dictionary<TKey, Func<>>

Sometimes there isn’t much common at all. Sometimes, the complexities very greatly.

public void Foo(int val, Obj a)
{
    switch (val)
    {
        case 0:
            // ... code goes here
            break;
        ....
    }
}

Imagine the code in the “code goes here” section is vastly different. Imagine you just can’t find much common ground. In these situations, you can use Dictionary<TKey, Func<>>. The pattern is to put the dictionary in its own class file. Then the object that uses it can have an injectable IDictionary<TKey, Func<>>. Injection options are: Constructor injection, Method injection, property injection. I lean toward a property injection variation called a Lazy Injectable Property.

Question: What generic paramaters should be used for the Dictionary?
Answer: The TKey is clearly the type of the val property, which in the example is an int.

Question: What generic parameters should be used for the Func<>?
Answer: Well, you need to think through to get this answer. First, you need to find the Lowest Common Parameter Set. Second you need to check the return type.

Finding the Lowest Common Parameter Set

If you look at one of the above methods, you can easily get the lowest common parameter set by writing down each and every parameter pass in. Remember this method from above in Example 2?

public void Foo(int val, ObjA a, ObjB b, ObjC c)
{
    // Switch/case statement here . . .
}

The lowest common parameter set is: a, b, c. If you look at the full implementation further up, you will notice that none of the methods take in val, so val is not included in the parameter set as it is the Dictionary’s key.

So now we can create our Dictionary. We will have three input parameters.

Note: Not all variables are passed in. Some may be local to the class or method.

Action<> vs Func<>

This is easy. The only notable difference is that Action<> takes in parameters and returns void. Func<> takes in parameters and returns the type specified in the last generic type.

So as there is no return value in the above example, we can use this code:

public Class FuncDictionary : Dictionary<int, Action<ObjA, ObjB, ObjC>>
{
    public FuncDictionary()
    {
        this.Add(0, (a, b, c) => { Bar.Do(a); } ); // Parameters b, c are ignored. That is ok.
        this.Add(1, (a, b, c) => { Bar.Do(b); } );
        this.Add(2, (a, b, c) => { Bar.Do(c); } );
        this.Add(3, (a, b, c) => { Bar.Do(a, c); } );
        this.Add(4, (a, b, c) => { Bar.Do(b, c); } );
        this.Add(5, (a, b, c) => { Bar.Do(b, c, a); } );
        this.Add(6, (a, b, c) => { Bar.Do(b, c, a * .01); } );
        this.Add(7, (a, b, c) => { Bar.Do(a, b, c); } );
    }
}

Now look at the foo code.

// Lazy injectable property
internal IDictionary<int, Action<ObjA, ObjB, Objc> ActionDictionary
{
    get { return _ActionDictionary ?? (_ActionDictionary = new FuncDictionary()); }
    set { _ActionDictionary = value; }
} private IDictionary<int, Action<ObjA, ObjB, Objc> _ActionDictionary;

public void Foo(int val, ObjA a, ObjB b, ObjC c)
{
    ActionDictionary[val].Invoke(a, b, c);
}

In all the previous methods, we resolved Cyclomatic Complexity by taking a method with 8 branches, and reducing that 1 method to 0 branches. We can also get 100% code coverage with 1 unit test.

1, Methods
0, Cyclomatic Complexity

In this final Dictionary<TKey, Func<>> example, we end up with 8 methods that need testing.

8, Methods
0, Cyclomatic Complexity each

We still have to test all 9 methods (8 funcs in in the FuncDictionary and the original method). However, when that work was in the switch/case statement, that code would be harder to isolate for unit tests. With the refactor to Dictionary<TKey, Func<>>, all eight methods are isolated and unit tests are simplified. The single responsibility is followed. The code is simply S.O.L.I.D. You could even inject interfaces with Dependency Injection that provide those methods. The Switch/Case statement appeared easier to write, but it usually leads to more code coupling, makes code harder to unit test and maintain; not to mention adds difficulty to future edits or replacing code, or the difficulty of dependency injection.


Three most basic rules every software developer should follow

  1. Model classes have properties and nothing more.
    Note: Properties are basically getter and setter methods. In languages without properties, getters and setters are the equivalent. Do not use getter or setter methods as methods for anything more complex than default instantiation of the type. Example: You can make sure a List is not null in a getter and lazy load it, but don’t do much more. Or a calculated property might have minor logic but it is all internal to the model.
  2. Any class with methods can reference primitives, collections and lists, interfaces, and model classes. Do not reference a class with methods directly from any other class. Reference another class through and interface.
  3. 10/100 Rule (Slightly bendable rule). No method should have more than 10 lines of code, including curly braces and comments. No Class should be more than 100 lines of code, including curly braces and comments.

Look, there is S.O.L.I.D., there is D.R.Y, there is S.R.P., and many other rules. There are design patterns, including the gang of four patterns, and many others. There are architectures, MVC, MVVM, etc. But if you, as a software developer, follow the above three rules, you will automatically end up following most of the other rules. Design patterns will naturally be used in your code, even if you don’t know them, though I recommend you still learn and know about them.


Back up and restore a single table with foreign keys using SQL Server

Today I needed to backup a single database table, then test a change to the data, then if the change failed, restore the original data.

Below is how I did this.

What I used

I used SQL Server Management Studio to do all of the following steps.
I performed the steps on a database running on a SQL 2012 database server.

Part 1 – Backup the table

SELECT *
INTO MyTable_Bak
FROM MyTable;

Note: This will work usually, however, it won’t work if you have a calculated column. If you have a calculated column, create the table first, then specify the columns you are inserting. I didn’t have a calculated column, so I didn’t take time to figure this out.

Part 2 – Restoring the table

Step 1 – Finding the Foreign Key Constraints

SELECT Name, Object_Name(parent_object_id) as [Table]
FROM sys.foreign_keys
WHERE referenced_object_id = object_id('MyTable')

The results were like this:

Name                    Table
FKDDED6AECAD1D93C0      MyOtherTable1
FK166B6670AD1D93C0      MyOtherTable2

Step 2 – Get the Drop and Create for each Foreign Key

In SQL Management Studio Express, I went to each table in the above list, and did the following:

  1. Locate the foreign key under Database | MyDb | Tables | dbo.MyTable | Keys.
  2. Right-click on the Foreign Key and choose Script Key as | Drop and Create to | Clipboard.
  3. Paste this into the query window.
  4. Delete the USING MyDb statement and separate the DROP statement from the two ALTER TABLE statements.
  5. Repeat for the next foreign key constraint, grouping the DROP statements and the ALTER TABLE statements together.

Step 3 – Run the DROP statements

Run the two DROP statements created above.

ALTER TABLE [dbo].[MyOtherTable1] DROP CONSTRAINT [FKDDED6AECAD1D93C0]
GO
ALTER TABLE [dbo].[MyOtherTable2] DROP CONSTRAINT [FK166B6670AD1D93C0]
GO

Step 4 – Restore the table

I used this query to restore the table from the backup.

SELECT * FROM MyTable
SET IDENTITY_INSERT dbo.MyTable ON; 
TRUNCATE TABLE MyTable ;
INSERT INTO MyTable (Id, Col1, Col2, Col3) -- Specify all columns here
SELECT (Id, Col1, Col2, Col3)              -- Specify all columns again here
FROM MyTable_Bak

Step 5 – Restore the foriegn key constraints

Run the ALTER TABLE scripts you grouped together from Step 2.

ALTER TABLE [dbo].[MyOtherTable2]  WITH CHECK ADD  CONSTRAINT [FKDDED6AECAD1D93C0] FOREIGN KEY([MyTableId])
REFERENCES [dbo].[MyTable] ([Id])
GO

ALTER TABLE [dbo].[MyOtherTable2] CHECK CONSTRAINT [FKDDED6AECAD1D93C0]
GO

ALTER TABLE [dbo].[MyOtherTable2]  WITH CHECK ADD  CONSTRAINT [FK166B6670AD1D93C0] FOREIGN KEY([MyTableId])
REFERENCES [dbo].[MyTable] ([Id])
GO

ALTER TABLE [dbo].[MyOtherTable2] CHECK CONSTRAINT [FK166B6670AD1D93C0]
GO

Conclusion

Your table is restored.

Observations

  1. This is a simple process for a table with only a few foriegn key constraints but could be difficult if you have dozens of foreign key constraints.
  2. Also, this process might not work perfectly with calculated columns without changes to the above process.
  3. It should be easier to do this.

If you know of a better way that doesn’t require $oftware, let me know.


Cleaning a customer folder in Visual Studio project

I have a Plugins directory in a Visual Studio project. I would like to delete all files from it when I clean.

Here is how I did this:

  1. Edit the .csproj file.
  2. Add the following to the very bottom of the .csproj file, just above the terminating </Project> tag.
      <Target Name="afterClean">
          <ItemGroup>
            <FilesToDelete Include="Plugins\**\*"/>
        </ItemGroup>
        <Delete Files="@(FilesToDelete)" />
      </Target>
    
  3. Save the .csproj file.

That should do it.

Update 12/14/2016:
You should be aware that when doing a custom clean, that in Visual Studio choosing Clean and then Build in two steps is not the same as doing Rebuild.

Clean <-- Cleans all projects Build <-- Builds all projects Rebuild <-- For each project, clean the project, then rebuild the project. So Rebuild is a huge problem and here is why: Since my code is pretty decoupled, my plugins don't reference the project hosting the plugins. So there is not dependency to guarantee the plugin-hosting project cleans and builds first. So when running reubild, a plugin might clean and build and then copy its files to the plugin directory. This could happen before the plugin-hosting project cleans and builds. So you can imagine that once the plugin-hosting project cleans and builds, the newly copied plugin files are cleaned. To fix this, I had to manually add a dependency or just not use Rebuild.


Constructor Injection Hell

So I am a fan of dependency injection (DI), inversion of control (IoC), and the way DI and IoC allow for simplistic methods and Unit Tests. With DI, you can do method injection, property injection, or constructor injection. I don’t care which one a project uses, as long as they keep it simple.

Constructor Injection

This article is focussing on constructor injection. Constructor injection seems to be very popular, if not the most popular method of DI. Constructor Injection is considered to have a benefit because it requires the instantiator to provide all the dependencies an object needs in order to create an instance of it.

An Example of Constructor Injection Hell

Recently, I started working with NopCommerce, which uses DI heavily. They use Autofac and register objects with Autofac so it can provide concrete instances of any interfaces.

I am going to use NopCommerce as an example of what not to do. Now before I do this, I want to explain that NopCommerce overall has a very good architecture. Better than most. Finding something that I consider a “what not to do” in a project should not steer you away from NopCommerce. In fact, their plugin model and architecture works quite well.

Below is an example of constructor injection gone wrong from the OrderProcessingService.cs file in NopCommerce.

#region Ctor

        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="orderService">Order service</param>
        /// <param name="webHelper">Web helper</param>
        /// <param name="localizationService">Localization service</param>
        /// <param name="languageService">Language service</param>
        /// <param name="productService">Product service</param>
        /// <param name="paymentService">Payment service</param>
        /// <param name="logger">Logger</param>
        /// <param name="orderTotalCalculationService">Order total calculationservice</param>
        /// <param name="priceCalculationService">Price calculation service</param>
        /// <param name="priceFormatter">Price formatter</param>
        /// <param name="productAttributeParser">Product attribute parser</param>
        /// <param name="productAttributeFormatter">Product attribute formatter</param>
        /// <param name="giftCardService">Gift card service</param>
        /// <param name="shoppingCartService">Shopping cart service</param>
        /// <param name="checkoutAttributeFormatter">Checkout attribute service</param>
        /// <param name="shippingService">Shipping service</param>
        /// <param name="shipmentService">Shipment service</param>
        /// <param name="taxService">Tax service</param>
        /// <param name="customerService">Customer service</param>
        /// <param name="discountService">Discount service</param>
        /// <param name="encryptionService">Encryption service</param>
        /// <param name="workContext">Work context</param>
        /// <param name="workflowMessageService">Workflow message service</param>
        /// <param name="vendorService">Vendor service</param>
        /// <param name="customerActivityService">Customer activity service</param>
        /// <param name="currencyService">Currency service</param>
        /// <param name="affiliateService">Affiliate service</param>
        /// <param name="eventPublisher">Event published</param>
        /// <param name="pdfService">PDF service</param>
        /// <param name="rewardPointService">Reward point service</param>
        /// <param name="genericAttributeService">Generic attribute service</param>
        /// <param name="paymentSettings">Payment settings</param>
        /// <param name="shippingSettings">Shipping settings</param>
        /// <param name="rewardPointsSettings">Reward points settings</param>
        /// <param name="orderSettings">Order settings</param>
        /// <param name="taxSettings">Tax settings</param>
        /// <param name="localizationSettings">Localization settings</param>
        /// <param name="currencySettings">Currency settings</param>
        public OrderProcessingService(IOrderService orderService,
            IWebHelper webHelper,
            ILocalizationService localizationService,
            ILanguageService languageService,
            IProductService productService,
            IPaymentService paymentService,
            ILogger logger,
            IOrderTotalCalculationService orderTotalCalculationService,
            IPriceCalculationService priceCalculationService,
            IPriceFormatter priceFormatter,
            IProductAttributeParser productAttributeParser,
            IProductAttributeFormatter productAttributeFormatter,
            IGiftCardService giftCardService,
            IShoppingCartService shoppingCartService,
            ICheckoutAttributeFormatter checkoutAttributeFormatter,
            IShippingService shippingService,
            IShipmentService shipmentService,
            ITaxService taxService,
            ICustomerService customerService,
            IDiscountService discountService,
            IEncryptionService encryptionService,
            IWorkContext workContext,
            IWorkflowMessageService workflowMessageService,
            IVendorService vendorService,
            ICustomerActivityService customerActivityService,
            ICurrencyService currencyService,
            IAffiliateService affiliateService,
            IEventPublisher eventPublisher,
            IPdfService pdfService,
            IRewardPointService rewardPointService,
            IGenericAttributeService genericAttributeService,
            ICompanyService companyService,
            ShippingSettings shippingSettings,
            PaymentSettings paymentSettings,
            RewardPointsSettings rewardPointsSettings,
            OrderSettings orderSettings,
            TaxSettings taxSettings,
            LocalizationSettings localizationSettings,
            CurrencySettings currencySettings)
        {
            this._orderService = orderService;
            this._webHelper = webHelper;
            this._localizationService = localizationService;
            this._languageService = languageService;
            this._productService = productService;
            this._paymentService = paymentService;
            this._logger = logger;
            this._orderTotalCalculationService = orderTotalCalculationService;
            this._priceCalculationService = priceCalculationService;
            this._priceFormatter = priceFormatter;
            this._productAttributeParser = productAttributeParser;
            this._productAttributeFormatter = productAttributeFormatter;
            this._giftCardService = giftCardService;
            this._shoppingCartService = shoppingCartService;
            this._checkoutAttributeFormatter = checkoutAttributeFormatter;
            this._workContext = workContext;
            this._workflowMessageService = workflowMessageService;
            this._vendorService = vendorService;
            this._shippingService = shippingService;
            this._shipmentService = shipmentService;
            this._taxService = taxService;
            this._customerService = customerService;
            this._discountService = discountService;
            this._encryptionService = encryptionService;
            this._customerActivityService = customerActivityService;
            this._currencyService = currencyService;
            this._affiliateService = affiliateService;
            this._eventPublisher = eventPublisher;
            this._pdfService = pdfService;
            this._rewardPointService = rewardPointService;
            this._genericAttributeService = genericAttributeService;
            this._companyService = companyService;

            this._paymentSettings = paymentSettings;
            this._shippingSettings = shippingSettings;
            this._rewardPointsSettings = rewardPointsSettings;
            this._orderSettings = orderSettings;
            this._taxSettings = taxSettings;
            this._localizationSettings = localizationSettings;
            this._currencySettings = currencySettings;
        }

        #endregion

Problems in the Constructor Injection Implementation

So what is wrong with the above constructor? Well, a lot. Look, this is just bad code. While constructor injection is a good idea, taking it to this extreme is not a good idea. In fact, it is a terrible idea.

  1. The Constructor has too many parameters. While there is no limit, there is a best practice. See this stack overflow post: How many parameters are too many?
  2. The Constructor breaks the 10/100 rule. The constructor, with comments, method parameters, and method body is 126 lines of code. The method itself is far more than 10 lines of code, it is 39 lines of parameters and 39 more lines of member assignments, and is 80 lines of code.
  3. The Constructor breaks the keep it super simple (KISS) principle. Having to new up 39 concrete instances of the parameters in order to create an object is not simple. Imagine mocking 39 interface parameters in a Unit Test. Ugh!
  4. This constructor is a hint that the entire class is doing too much. The class is 3099 lines and clearly breaks the single responsibility principle. It is not the OrderProcessingService’s responsibility to store 39 dependent services.
  5. The constructor breaks the Don’t Repeat Yourself (DRY) principle. Almost all other classes in NopCommerce use constructor injection to access services.

Options for Refactoring

Option 1 – Container object

You could create a container that has all of these dependecies, a dependency model object for the OrderProcessingService. This object would house the 39 dependent services and settings. But Option 2 would be better.

Option 2 – Accessor objects

Looking at this from the Single Responsibility Principle, shouldn’t there be one class and interface, a ServiceAccessor : IServiceAccessor that allows one to access any dependent service? Instead of passing in 30 services, wouldn’t it make more sense to pass in a single object called a ServiceAccessor that implements IServiceAccessor? Should there be a ServiceAccessor of some sort? Turns out there is a static: EngineContext.Current.Resolve(). Since it is a static, maybe you could wrap it in a ServiceAccessor : IServiceAccessor object.

There are also a lot of “settings” objects passed into the constructor? Shouldn’t there be a SettingsService? Well, there is. One can pass in the ISettingsService and then call _settingService.LoadSetting().

Instead of passing in 39 parameters, methods with a single responsibility to fetch a service should be used.

Option 3 – Refactor the class

Since the class is 3099 lines. If the class were broken into logical pieces, naturally, the constructor for each smaller piece would have less parameters.


How to convert a string to an enum in C#?

Use this extension method:

using System;

namespace Rhyous.Extensions
{
    public static class StringExtensions
    {
        public static T AsEnum<T>(this string str, T defaultValue)
        {
            try { return (T)Enum.Parse(typeof(T), str, true); }
            catch { return defaultValue; }
        }
    }
}

So imagine you have this enum:

public enum LogLevel
{
   Debug,
   Information,
   Warning,
   Error,
   Fatal
}

Call it like this:

var levelStr = "Error";
LogLevel level = levelStr.AsEnum(LogLevel.Info);

Unit testing calls to complex extension methods

This article isn’t about unit testing an extension method. That is pretty straight forward. This article is about unit testing and object that calls an extension method where the extension method is difficult to test. Likely the method is difficult to test because it touches an external system, such as a database or a remote web service.

If you have an extension method that is simple and doesn’t touch and external system, it is easy to unit test. Look at the example below. There is nothing blocking you from Unit Testing code that calls this method.

public static int Add(this int left, int right) 
{
    return left + right;
}

Now image the extension method is more complex, say for a shopping cart.

public static void PlaceOrder(this Order order) 
{
    SaveToDb(Order);
    ChargeCreditCard(Order.CreditCardDetails);
}

How are you going to unit test code that calls an extension method that place an order and charges a customer’s Credit Card. Yikes. That is little harder to Unit Test, right?

How to Unit Test a call to a complex extension method

Imagine you have the following code:

  1. An object you are test called ObjectUnderTest
    public class ObjectUnderTest
    {
        private void MyObject = new MyObject();
    
        public object SomeFunction() 
        {
            return myObj.DoWork(val);
        }
    }
    
  2. An dependent object MyObject : IMyObject
    public class MyObject : IMyObject
    {
     // ... some code
    }
    
  3. An extension method on IMyObject: DoWork(this IMyObject obj, string value).
    public static object DoWork(this IMyObject obj, string value)
    {
        // really complex stuff and touches external systems
    }
    

You need Unit Tests for SomeFunction(). Imagine that all other code is 100% unit tested. But you are struggling with how to Unit Test SomeFunction because it has two dependencies:

  1. MyObject
  2. DoWork

The Unit Tests should not call the real DoWork because it does really complex stuff and touches external systems. However, you need the parent method to provide a valid return value.

Well, you could just drop the ExcludeFromCodeCoverageAttribute on the method and move on. But what if there are a half-dozen other objects that call the parent method that also need to be tested and they need a return value from SomeFunction()? It would be best to solve this in this object as so you only change one class file, not a half-dozen.

One option to resolve this is to use dependency injection. Dependency Injection (DI) simply means that any dependencies can be injected. When some people hear DI, they think they immediately need the huge overhead of an IoC Container. IoC containers are nice and have their uses. But using an IoC container only to allow unit tests substitute a dependency is a huge overkill. If your project already has an IoC container, feel free to use it. Otherwise, I recommend you use a simpler option. I prefer an internal lazy injectable property.

Creating a Lazy Injectable Property

An internal lazy injectable property is a property that is instantiated on first use if it is null, but always for code with internal access to swap out the property value. Here is the syntax:

Note: This assumes your unit tests references your project already, has InternalsVisibleTo configured, and has Moq from NuGet applied to the test project.

    internal IMyObject MyObjectProperty
    {
        get { return _MyObject ?? (_MyObject = new MyObject()); }
        set { _MyObject= value; }
    } private List<object> _MyObject;

Look how simple the above code is. If _MyObject is null, the first time MyObjectProperty is called, it is instantiated to a new MyObject().It is internal because only the unit test will every replace it. I don’t really want this property exposed elsewhere. We can use InternalsVisibleTo to allow the Unit Tests access.Now my ObjectUnderTest will look like this:

public class ObjectUnderTest
{
    internal IMyObject MyObjectProperty
    {
        get { return _MyObject ?? (_MyObject = new MyObject()); }
        set { _MyObject= value; }
    } private IMyObject _MyObject;

    public object SomeFunction()
    {
        var val = "doesn't matter for this example";
        return MyObjectProperty.DoWork(val);
    }
}

Now, in the unit test, the MyObjectProperty can be replaced with a mock IMyObject.

[TestMethod]
public void SomeFunctionTest()
{    // Arrange
    var mockMyObject = new Mock<IMyObject>();
    var objUnderTest = new ObjectUnderTest();
    objectUnderTest.MyObjectProperty = mockMyObject.Object;

    // More to come . . .
}

However, it is questionable whether this is even necessary. Does MyObject do anything that requires this level of abstraction? Not in this example. It isn’t the object itself that is complex, it is the extension method that really needs to be injectable.

Creating a Lazy Injectable Property for a method

You might be asking yourself, “What about the extension method? It is a method not an object. How can I inject that?” Well, you can. Remember, even methods can be treated as objects. The answer doesn’t change much. The only difference is understanding how to treat a method as an object.You can objectify methods using multiple objects such as Action, Func, Predicate, delegate, etc. I am not going to go into how to do that here beyond the minimal needed to accomplish this task.

Quick tip: Use Action for void methods, Predicate for methods return bool, Func for methods with any return value, delegate if you have ref or out paramters.

Here are the steps:

  1. Create the following Lazy Injectable Property inside ObjectUnderTest:

    Note: I am using Func because it has a return value of object. (See the Quick Tip a few lines up.) Since I have two paramters and a return type, I will specifically use the generic Func.

        internal Func<IMyObject, string, object> DoWorkMethod
        {
            [ExcludeFromCodeCoverage]
            get { return _DoWorkMethod ?? (_DoWorkMethod = (obj, val) => { return obj.DoWork(val); }); }
            set { _DoWorkMethod = value; }
        } private Func<IMyObject, string, object> _DoWorkMethod;
    
  2. Change SomeFunction() to run the method via the Action object instead of running the method directly.
        public object SomeFunction()
        {
            var val = "doesn't matter for this example";
            return DoWorkMethod.Invoke(MyObjectProperty, val);
        }
    
  3. In your Unit Test, you can create your ObjectUnderTest. Then you can swap out the DoWork method object.
    [TestMethod]
    public void SomeFunctionTest()
    {
        // Arrange
        var mockMyObject = new Mock<IMyObject>();
        var objUnderTest = new ObjectUnderTest();
        objUnderTest.MyObjectProperty = mockMyObject.Object;
        bool methodWasCalled = false;
        objUnderTest.DoWorkMethod = (obj, val) => {
            methodWasCalled = true;
            return new object();
        };
            
        // Act
        var result = objUnderTest.SomeFunction();
    
        // Assert
        Assert.IsTrue(methodWasCalled);
    }
    

You are now 100% covered. The only code we can’t cover is the lambda call to obj.DoWork because we can’t Unit Test that as it touches an external system. Which is why we marked it with the ExcludeFromCodeCoverageAttribute.


A SerializableDictionary in C#

If you create a static Dictionary in code, every time you need to change the dictionary, you have change code, recompile, and redeploy. Wouldn’t it be nice if you didn’t have to change code. What if you could create your dictionary in an Xml file and deserialize it. You can now make the change outside of code.

using System.Collections.Generic;
using System.Xml.Serialization;

namespace Rhyous.EasyXml
{
    [XmlRoot("Dictionary")]
    public class SerializableDictionary<TKey, TValue>
        : Dictionary<TKey, TValue>, IXmlSerializable
    {
        public string KeyName = "key";
        public string ValueName = "value";

        #region constructors
        public SerializableDictionary()
        {
        }

        public SerializableDictionary(IEqualityComparer<TKey> comparer)
            : base(comparer)
        {
        }
        #endregion



        #region IXmlSerializable Members
        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(System.Xml.XmlReader reader)
        {
            var keySerializer = new XmlSerializer(typeof(TKey), null, null, new XmlRootAttribute(KeyName), null);
            var valueSerializer = new XmlSerializer(typeof(TValue), null, null, new XmlRootAttribute(ValueName), null);

            var wasEmpty = reader.IsEmptyElement;
            reader.Read();

            if (wasEmpty)
                return;

            while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
            {
                var key = (TKey)keySerializer.Deserialize(reader);
                var value = (TValue)valueSerializer.Deserialize(reader);
                Add(key, value);
                reader.MoveToContent();
            }
            reader.ReadEndElement();
        }

        public void WriteXml(System.Xml.XmlWriter writer)
        {
            var keySerializer = new XmlSerializer(typeof(TKey));
            var valueSerializer = new XmlSerializer(typeof(TValue));

            foreach (TKey key in Keys)
            {
                keySerializer.Serialize(writer, key);
                valueSerializer.Serialize(writer, this[key]);
            }
        }
        #endregion
    }
}

Code faster and with higher quality using code generation

Code generation is the idea of having a tool write code written for you. If you use a modern IDE, such Visual Studio, you likely use a type of code generation, even if you think you don’t.

Anytime code is written for you, it is code generation. You use code generation whenever you do the following:

  1. Create a new solution or project – Each project is a template with a base set of code ready for you to use.
  2. Add a new class, interface, or another item to a project – When adding a new class to a project, the class comes with a pre-created class object. If you add a new class called Person, the following class file would be created and added to the project:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace LANDesk.Licensing.WebServices.File.Tests
    {
        class Person
        {
        }
    }
    

    The using statements are lines of code. The namespace and class definitions and the brackets are lines of code.  You get 11 lines of code not including the whitespace lines. This code was created for you because you didn’t have to write it. That doesn’t mean it is 100% useful. If you don’t use threading, the last using statement can be removed.

    Similarly, other items that are added have a base set of code.

  3. Use code snippets – Code Snippets are quite powerful. With a few characters and then the tab key twice, you can create a lot of code. There are many built-in code snippets. If you are using them, you should be.
  4. Other Visual Studio features – Visual Studio has some specific use cases where it provides code generation. For example, if you highlight a class name and choose Extract Interface, Visual Studio will generate and interface from the
  5. Plugins and 3rd party tools – Many plugins can generate code for you. For example, Resharper can do numerous code generation features, such as properly overriding the Equals method. ORMs, such as Entity Framework, have code generation tools. Entity Framework can generate most the Entities (class files that represent objects stored in database tables)  for you.

You can enhance the code generation tools

Most of these features are available as platforms for you to build upon. Enhancing these can be a simple as copying an existing item or as complex as developing your own product.

In Visual Studio, you can do any of the following: (listed in order of ease of use)

  1. Create your own snippets.
  2. Create your own class/item templates
  3. Download or purchase additional code generation plugins
  4. Create your own Project/Solution templates
  5. Create your own Visual Studio plugins/3rd party tools

If you are repeatedly writing the same code over an over again, you probably would benefit from creating a code generation solution.

Faster and higher Quality

When a human writes something, there is room for human error. If a person writes the same thing over and over, there is a tendency to minimize and cut corners. Also, there are many standard pieces of code that have already gone through significant use and bug fixes resulting in a stable and scalable piece of code. For example, overriding Equals in a class isn’t always straight forward. If you do it yourself, you might be left wondering if you have properly overridden Equals of if your implementation has well-known bugs? Do you leave those bugs in or research and fix them? If you research and fix them, how long will it take you each time you override Equals to make sure you accounted for all well-known bugs? However, if you use a generator with a standard, tested, and bug-free piece of code, your code will be higher quality and it will be created almost instantly. See, faster and higher quality.

I am hoping to have time to create a series of posts on this topic, starting with Snippets. But to get you started, check out my Visual Studio snippets for C# on GitHub.

https://github.com/rhyous/VisualCSharpSnippets

 


Using a method for the sole purpose of documentation

Some developers like to write one line of code for complex tasks. It’s called code golf and there is a whole subdomain on StackExchange dedicated to code golf. Also, I have seen an idea mentioned on some forums that you should never have a method that is a single line of code. I am going to challenge that statement and suggest that when a single line of code is difficult to understand, wrapping it in a method for the sole purpose of readability is a good practice to follow.

Below is an example of one line of code.

for (int i = 0; i < max; i++) { wsProducts[i].Features = dbContext.Products.Select(p=>p.Id == wsProducts.Id).Features.Select(f=>f.ToServiceObj()).ToList(); }

I am not going to argue whether one line of code is good or bad to have on one line. I like my for loops to be broken out like this.

for (int i = 0; i < max; i++) 
{ 
  wsProducts[i].Features = dbContext.Products.Select(p=>p.Id == wsProducts.Id).Features.Select(f=>f.ToServiceObj()).ToList();
}

But I am not going to dictate my personal preference onto other developers. That is not the point of this article. The point of this article is to talk about the benefit of a method for the sole purpose of documentation and making the code more readable. Besides, there are hundreds of other single lines of code that are difficult to understand. Thanks to Linq alone, C# now has plenty of examples. But this isn’t just a C# concept. This concept work in C++, Java, JavaScript, or any language. This concept is language agnostic.

So to start with, what is the above code doing? Can you tell from this line of code? I couldn’t at first glance. I had to examine it further. Who wrote this. (Hopefully, it wasn’t me two years ago. It probably was.)

Well, my ORM has Products and each product has a list of Features. My WebService also has Products and each Product has a list of Features. However, the ORM Product and Feature classes are not the same object types as the WebService Product and Feature classes. They are different objects in different namespaces. So basically, this code gets the list of features foreach product from the database and converts the features to a WebService Feature type, puts them in a list and assigns them to the WebService Product type’s feature list.

Wait, why did I have to explain that to you. Why didn’t you simply know what the code did? Because the code is not self-explanatory. Is is not easy to read or understand.

What if instead of our embedding our loop in our current code, we created and called this method instead?

GetFeaturesFromDatabase(MyDbContext dbContext, IEnumarable<MyWebService.Product> wsProducts) 
{
  for (int i = 0; i < max; i++) { wsProducts[i].Features = dbContext.Products.Select(p=>p.Id == wsProducts.Id).Features.Select(f=>f.ToServiceObj()).ToList(); }
}

Basically, we encapsulate (did I just use the term encapsulation outside of a CS 101 course) the complex code in a method and use the method instead.

GetFeaturesFromDatabase(dbContext, wsProducts);

Is that not clearer and easier to read?

But should we do this?

Let’s assume that our code already uses dependency injection and we already can mock the dbContext, and our code already has Unit Tests that are passing. So we don’t really need this method for any other reason other than documentation.

My answer is YES! Yes, using a method for the sole purpose making the code self-documenting and easier to read is worth it.

What do you think?


SQL Query to Entity Framework Cheat Sheet

The following are examples of SQL queries and how to execute them with Entity Framework

SELECT * with Entity Framework

SELECT * FROM Contacts
var mydbContext.Contacts.ToList();

SELECT Id with Entity Framework

This is really for how to select any single column.

SELECT Id FROM Contacts
List<int> idList = dbContext.Contacts.Select( c => c.Id ).ToList(); // Assuming Id is of type int

SELECT only one row with Entity Framework

This is really for how to select any single row from a table.

SELECT * FROM Contacts where Id = 10
var id = 10;
var contact = dbContext.Contacts.SingleOrDefault( c => c.Id = id );

SELECT only one result with Entity Framework

This is really for how to select any single value from a single row in a table.

SELECT UserId FROM Contacts where Id = 10
var id = 10;
int userId = dbContext.Contacts.Where( c => c.Id = id ).Select( c => c.UserId ).SingleOrDefault();

SELECT first result with Entity Framework

This is really for how to select the first value from a list of returned rows from a table.

SELECT TOP 1 * FROM Contacts
var id = 10;
int userId = dbContext.Contacts.FirstOrDefault();

INSERT INTO with Entity Framework

INSERT INTO dbo.LD_User (Name, Type, Active, CreateDate, CreatedBy)
VALUES ('user1', 1, 1, GetDate(), 101)
var user = new User { Name = "user1", Type = UserType.Contact, true, DateTime.Now, User.System };
dbContext.Users.Add(user);
dbContext.SaveChanges();

Note: UserType.Contact and User.System are enums in the above example.

INSERT INTO … SELECT with Entity Framework

Imagine you have these three tables. Product, ProductGroup, ProductGroupMembership. You want to make Products a member of a group by inserting into the ProductGroupMembership table.

INSERT INTO ProductGroupMembership (ProductId, GroupId, CreateDate, CreatedBy)
SELECT Id, @GroupId, GetDate(), @CreatedBy FROM Product
WHERE Id IN (1, 2, 3, 4, 5) -- there could be hundreds or thousands of numbers in the IN statement
EPIC FAIL!!! Can't be done without raw sql and opening up to sql injection attacks.

However, you can create a stored procedure that takes and user-defined table called ArrayOfInt. Then add EntityFrameworkExtras.EF6, which is available as a NuGet package, to call the storedprocedure and pass it an array.

WHERE with many AND/ORs with Entity Framework

Imagine you have these three tables. Product, ProductGroup, ProductGroupMembership. You want to make Products a member of a group by inserting into the ProductGroupMembership table.

You have a list of software Products provided to you. However, the input only includes Product.Name and Product.Version. You now need to check if the products exist and get the id.

SELECT Id FROM Product
WHERE (Name = 'Product 1' AND Version = '10.0')
WHERE (Name = 'Product 2' AND Version = '10.0')
WHERE (Name = 'Product 3' AND Version = '10.1')
WHERE (Name = 'Product 4' AND Version = '10.0')
WHERE (Name = 'Product 5' AND Version = '1.0')
EPIC FAIL!!! Can't be done without raw sql

However, you can add LinqKit’s PredicateBuilder to do this. PredicateBuilder works on top of Entity Framework and is available as a NuGet package. See how I used it here: Entity Framework and many WHERE clauses


How to create a WordPress content filter plugin?

It is pretty easy to roll out a WordPress plugin that adds a content filter.

Creating a WordPress content filter plugin

Here are the basic steps to replace the content with a filter. This example is very rudimentary and replaces all of the content, which you would probably never really do.

  1. Create a new file called MyPlugin.php
  2. Add this code:
    <?php
    /*
    Plugin Name: <Your Plugin Name>
    Version: 1.0
    Plugin URI: tba
    Description:
    Author: <your name>
    Author URI: <your web site>
    */
    
      function handleContentFilter( $content = null ) {
        return "Hello, World!";
      }
    
      $test = add_filter( "the_content", "handleContentFilter" );
    
    ?>
    
  3. Upload (or copy) MyPlugin.php to the /wp-content/plugins/ directory in your WordPress install.

Replace content based on a search string

This is more likely what you are going to do. Sames steps as above, but change the file as follows:

  function handleContentFilter( $content = null ) {
    return str_replace("FindMe","Hello, World!", $content);
  }

Using a WordPress shortcode plugin

  1. Start a new Post
  2. type in the following:

    FindMe

  3. Click Preview.

Your post should have replaced FindMe with “Hello, Word!”.

A better WordPress content filter plugin template

While the above is all you need, a more scalable solution might involve using classes. Here is a template that uses classes.

<?php
/*
Plugin Name: <Your Plugin Name>
Version: 1.0
Plugin URI: tba
Description:
Author: <your name>
Author URI: <your web site>
*/

// A class to manage your plugin
class MyPlugin {
 
  public function MyPlugin( $shortCodeHandler ) {
    $result = add_filter( 'the_content', array( $shortCodeHandler, 'handleContentFilter' ) );
  }
 
}
 
// A class to handle your shortcode
class ContentFilterHandler {
 
  public function handleContentFilter( $content = null ) {
    return str_replace("FindMe","Hello, World", $content);
  }
 
}
 
$contentFilterHandler  = new ContentFilterHandler();
$plugin = new MyPlugin( $contentFilterHandler  );

?>

How to create a WordPress shortcode plugin?

It is pretty easy to roll out a WordPress plugin that adds a shortcode.

Creating a WordPress shortcode plugin

Here are the basic steps:

  1. Create a new file called MyPlugin.php
  2. Add this code:
    <?php
    /*
    Plugin Name: <Your Plugin Name>
    Version: 1.0
    Plugin URI: tba
    Description:
    Author: <your name>
    Author URI: <your web site>
    */
    
      function handleShortcode( $atts, $content ) {
        return "Hello, World!";
      }
    
      $test = add_shortcode( 'my-shortcode', 'handleShortcode' );
    
    ?>
    
  3. Upload (or copy) MyPlugin.php to the /wp-content/plugins/ directory in your WordPress install.

Using a WordPress shortcode plugin

  1. Start a new Post
  2. type in the following:

    [my-shortcode]

  3. Click Preview.

Your post should have replaced your shortcode with “Hello, Word!”.

A better WordPress shortcode plugin template

While the above is all you need, a more scalable solution might involve using classes. Here is a template that uses classes.

<?php
/*
Plugin Name: <Your Plugin Name>
Version: 1.0
Plugin URI: tba
Description:
Author: <your name>
Author URI: <your web site>
*/

// A class to manage your plugin
class MyPlugin {
 
  public function MyPlugin( $shortCodeHandler ) {
    $result = add_shortcode( 'my-shortcode', array( $shortCodeHandler, 'handleShortcode' ) );
  }
 
}
 
// A class to handle your shortcode
class ShortCodeHandler {
 
  public function handleShortcode( $atts, $content ) {
    return "Hello, World";
  }
 
}
 
$shortCodeHandler = new ShortCodeHandler();
$plugin = new MyPlugin( $shortCodeHandler );

?>

SQL Addendum Table

I have an application I am building that needs to be malleable. It is a data-driven application. It will have users, contacts, organizations, and many other objects represented as a database table. One goal of this project is to allow for extension. Some customers are going to want to add a field to an object that our tables don’t include. We want to handle this end to end. It seems the perfect use of a property value table.

It would be pretty easy to create an Addendum table for each object.

dbo.Organization
dbo.OrganizationAddendum
dbo.User
dbo.UserAddendum

While that is OK, it requires additional work every time a table is created. What if a Partner writes a plugin and adds an object in the database? Well, unless the Partner creates an addendum table, this won’t really work.

Is there a way to solve this so any object in the database can have Addendum data?

I came up with this table.

CREATE TABLE [dbo].[LD_Addendum](
	[Id] [int] IDENTITY(1,1) NOT NULL,
	[Table] [nvarchar](100) NOT NULL,
	[TableId] [int] NOT NULL,
	[Property] [nvarchar](255) NOT NULL,
	[Value] [nvarchar](255) NOT NULL,
	[CreateDate] [datetime2](7) NOT NULL,
	[LastUpdated] [datetime2](7) NULL,
	[CreatedBy] [int] NOT NULL,
	[LastUpdatedBy] [int] NULL,
 CONSTRAINT [PK_Addendum_Id] PRIMARY KEY CLUSTERED 
(
	[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY])

Then in the Web interface, I could have single template control that works for any object. Whatever object I am editing, be it user, contact, organization or other, the control would exist. If a partner adds a plugin with a new object, the control would exist. Seems easy enough, right?

The problem comes in with some of the features that we would like to be automatically handled on the database side:

  1. Table should have Id column
  2. Table should have four main fields
    • Table <– Database table to add addendum data for
    • TableId <– The row of in the table that addendum is for
    • Property <– The property of the addendum
    • Value <– the value of the addendum data
  3. Table should have the four auditing fields in IAuditTable
    • CreateDate
    • CreatedBy
    • LastUpdated
    • LastUpdatedBy
  4. Only one Property of the same name should exist per table and id. Easily done with a Unique constraint.
  5. Table should have a constraint that enforces that table must exist.
    I found a way to do this: I created User-defined Function (UDF) and check constraint that uses the UDF.

    CREATE FUNCTION [dbo].[TableExists](@TableName NVARCHAR(255))
    RETURNS bit
    AS
    BEGIN
    RETURN ((SELECT COUNT(TABLE_NAME) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @TableName))
    END
    
  6. Table should have a constraint that enforces that TableId must exist in the Table
    1. Not supported – CLR UDFin C#? Or handle this in code?
  7. The row should delete when Table is deleted. Similar to ON DELETE CASCADE.
    • Not supported – CLR UDFin C#? Or handle this in code?
  8. The row should delete when a row from a table that matches Table and Id is deleted. Similar to ON DELETE CASCADE.
    • Not supported – CLR UDFin C#? Or handle this in code?

Perhaps we ignore the missing features from database side and handle them with code?

Or perhaps another database system other than Microsoft SQL Server (such as Postgresql) could do this?

Scaling

Assuming I got this to work, I see one main problem: Table size. However, I am not sure this is an issue. Tables can quite large, millions of rows. If this table got too big, then we could investigate why, analyze the table, and perhaps move a property value from the Addendum table to an actual column in a real table. This should replace the ability to create a plugin with an additional table, but it should make it so few plugins are needed as there is more extensibility out of the box.

Also, we found that default values often alleviate addendum tables. For example, imagine adding an addendum item to an organization, ContactIntervalInDays. Say a company is supposed to contact their customers every 90 days. However, some customers might require more or less contact. However, the default is 90. Instead of adding 90 to all customers, you set a default. If ContactIntervalInDays is not in the Addendum table, then use 90, otherwise use the value.

Anyway, it seems like an Addendum table is something that most projects and solutions, such as CRMs, Shopping Carts, ERPs, etc. should implement. It won’t solve the most complex issues with extending a product, but it would perhaps solve many of them. The more complex extension can continue to be added via a well-designed plugin architecture.

Unfortunately, this simplistic solution is not supported. The recommendation is to have 1 addendum table for every regular table. Ugh! That doesn’t scale and is not maintainable long term.

Still, I went ahead and requested this feature from the SQL team.


Entity Framework and many WHERE clauses

So today, I needed to get Entity Framework to return me a list of Products from the database based on a list of Product.Name and Product.Version values (not Ids). If it were Product.Id, it would have been simple as I could have used an IN statement, but it wasn’t.

The query might get many (maybe hundreds at a time) products based on the list. Here is the query I imagined.

So when doing a query like this, since there could be hundreds, I have a couple of options.

  1. Query the database once for each product.
    SELECT * FROM dbo.Product
    WHERE (Name = 'Product 1' AND Version = '10.0')
    

    Repeat this same query once for each Product.

  2. Query the database one time with an or clause for each Product.Name and Product.Version.
    SELECT * FROM dbo.Product
    WHERE (Name = 'Product 1' AND Version = '10.0')
       OR (Name = 'Product 2' AND Version = '10.0')
       OR (Name = 'Product 3' AND Version = '10.0')
       OR (Name = 'Product 4' AND Version = '1.0')
       -- There could be hundreds
    
  3. Query the database once and get all products and use code to find the ones I wanted.
    SELECT * FROM dbo.Product
    

Option 1
I didn’t like this option because I could end up doing hundreds of single queries. That doesn’t sound like a good idea. What would the performance impact would be when doing hundreds of single queries? The overhead of traversing over the network to the database would prevent this option from scaling.

Option 2
This is the option I imagined in my head. My gut said to use this option.

Option 3
This would work. We only have about two thousand products today and querying them all would, right now, not be bad at all. However, we just bought a company and will be adding more products. We plan to buy more companies. Also, we have two companies that we have already bought and have yet to add those products in. When would the number of Product rows in the database make the SELECT * and invalid option? Doing this would work now, but it leave a time bomb for some future developer encounter and have to fix.

Winner: Option 2

Problem
Entity Framework doesn’t really have an easy way to create the Option 2 query.

So, how do I create this query with many where statements?

Here are the two options I’ve found:

Inline SQL Query with Entity Framework

        private static List<Product> GetProductsByNameAndVersion(ActivationDbContext dbContext, IEnumerable<ProductRequest> products)
        {
            if (!products.Any())
            {
                return new List<Product>();
            }
            var query = "Select * FROM Product WHERE ";
            var or = "";
            var template = "(Name = '{0}' AND Version = '{1}')";
            foreach (var prod in products)
            {
                query += or;
                query += string.Format(template, prod.Name, prod.Version);
                or = " OR ";
            }
            var dbProducts = dbContext.Products.SqlQuery(query).ToList();
            return dbProducts.ToList();
        }

This option means I have to create magic strings and make sure that I handle the strings correctly. It has bugs already. Such as what if a product only has a name and not a version (version could be null or empty, who knows) or vice-versa? How would this affect my query string?

PredicateBuilder

Predicate Builder from the LinqKit library which is available as a NuGet package.

        private static List<Product> GetProductsByNameAndVersionPredicate(ActivationDbContext dbContext, IEnumerable<ProductRequest> products)
        {
            if (!products.Any())
            {
                return new List<Product>();
            }

            var predicate = PredicateBuilder.False<Product>();

            foreach (var prod in products)
            {
                var inner = PredicateBuilder.True<Product>();
                inner = inner.And(p => p.Name== prod.Name);
                inner = inner.And(p => p.Version == prod.Version);
                predicate = predicate.Or(inner);
            }
            var dbProducts = dbContext.Products.AsExpandable().Where(predicate).ToList();
            return dbProducts;            
        }

PredicateBuilder isn’t very intuitive. For starters, what is the different between these methods:

  • PredicateBuilder.True() – from what I understand this would be more appropriate and understandable as PredicateBuilder.And()
  • PredicateBuilder.False() – from what I understand this would be more appropriate and understandable as PredicateBuilder.Or()

Also, you have to remember to call AsExpandable() on the first call to a table in order to use it.

Conclusion

I am going to go with PredicateBuilder for now. It feels cleaner than rolling my own string query. But both solutions ultimately worked. That means that Entity Framework ultimately provided me a solution without an extra library. However, LinqKit saved me from magic strings. My only question is this: Why isn’t a predicate builder built into Entity Framework?