Search code examples
c#entity-frameworkusingoptional-parameters

Optional context parameter in using statement


I have this method

public static List<_Account> Get(_User user, string name = null, SearchType sName = SearchType.Equals)
{
  using (Context context = new Context())
  {
    IQueryable<_Account> query = context.Accounts;
    if (!string.IsNullOrEmpty(name) && sName == SearchType.Equals)
      query = query.Where(r => r.Name.Equals(name));
    if (!string.IsNullOrEmpty(name) && sName == SearchType.StartsWith)
      query = query.Where(r => r.Name.StartsWith(name));
    if (!string.IsNullOrEmpty(name) && sName == SearchType.Contains)
      query = query.Where(r => r.Name.Contains(name));
    return query.ToList();
  }
}

This works but when i calling this method from another Method where I already defined a context I want to reuse that context. I would add an optional parameter

public static List<_Account> Get(..., Context ctx = null) {...

If ctx != null I want that context to be used and not disposed at the end. Else I want the context created in the using being used and disposed at the end of the method.


Solution

  • You can put null into a using block, so the following works:

    public static List<_Account> Get(_User user, Context contextProvided = null, string name = null, SearchType sName = SearchType.Equals)
    {
      using (Context contextInner = (contextProvided == null ? new Context() : null)) //magic here
      {
        Context context = contextProvided ?? contextInner; //magic here
    
        IQueryable<_Account> query = context.Accounts;
        if (!string.IsNullOrEmpty(name) && sName == SearchType.Equals)
          query = query.Where(r => r.Name.Equals(name));
        if (!string.IsNullOrEmpty(name) && sName == SearchType.StartsWith)
          query = query.Where(r => r.Name.StartsWith(name));
        if (!string.IsNullOrEmpty(name) && sName == SearchType.Contains)
          query = query.Where(r => r.Name.Contains(name));
        return query.ToList();
      }
    }
    

    Another good way to do it would be extract the flesh of the method (the query) into a helper method. Then, you can duplicate the now outer method into two overloads. One overload creates a context, one of them takes it as an argument.

    If this pattern happens a lot you could achieve something like this by creating a custom IDisposable derived class:

    public static List<_Account> Get(_User user, Context contextProvided = null, ...)
    {
      using (var contextProvider = new ContextProvider(contextProvided))
      {
        Context context = contextProvider.EffectiveContext;
        //...
      }
    }